שאלה ב- C++

שאלה ב- C++

קייםן פרוסס המעלה כמה threads.
בכל thread קוראים בתוך class לפונקציית winapi שאחד הפרמטר שלה הוא callback function.
ב- callback פונים לאחד ממשתני המחלקה המקומיים.

להבנתי ה- callback חייב להיות פונ' static.
במקרה כזה מה עושים עם המשתנה? אם אגדיר אותו כ- static הוא לא יוכר בין ה- threads? כי אם כן אז זה לא טוב לי
 
אין עוד פרמטר, שנשלח אח"כ ל-callback?

אני לא כ"כ בקיא בנושא, אבל אם אין, הייתי מציע שהמשתנה הסטטי יהיה מפה כלשהי בין ה-threads ובין המשתנה שאת צריכה.
 
חשבו על הבעיה הזו לפניך ואחד הפרמטרים שאת יכולה להעביר הוא איזשהו context או פרמטר כלשהו שמועבר ל callback כשהוא נקרא. את יכולה להשתמש בזה כדי להעביר פוינטר ל this של האובייקט שאת רוצה, ואז לקרוא למתודה לא-סטטית שלו. בכל פונקציית winapi שעובדת עם callback-ים זה קיים, ואני בטוח שגם בשלך. אם תתני את השם שלה נוכל לעזור לך.

זו שאלה מאוד נפוצה ונמצאת ב FAQ של שפת ++C, הנה כאן:
http://www.parashift.com/c++-faq/memfnptr-vs-fnptr.html

וההסבר שלהם:

The system call that starts a thread, for example, might require you to pass a function pointer along with a void*, so you can pass the object pointer in the void*.
 
תודה. האמת שכבר חשבתי על זה אבל

לא מצאתי משתנה כזה.
שם פונקציית API:
MQReceiveMessage

http://msdn.microsoft.com/en-us/library/windows/desktop/ms699825(v=vs.85).aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/ms699828(v=vs.85).aspx


VOID CALLBACK fnReceiveCallback(
HRESULT hr,
QUEUEHANDLE hQueue,
DWORD dwTimeOut,
DWORD dwAction,
MQMSGPROPS * pmsgprops,
LPOVERLAPPED pov,
HANDLE hCursor
)

לא ברור היכן המשתנה. מה אני מפספסת?
 
I think you need to implement it yourself

As no 'context' is provided, you'll have to hack a 'this' pointer into the callback declaration.
Just google 'member method winapi callback' and follow sample code.
 
תודה. במקרה שלי אין *void בפונקציית API

אז לא הבנתי איך להעביר this אשמח אם תוכל לתת דוגמת קוד לכך.
לא מצאתי לינק מתאים
 
במקרה של callback function

לא אמורים להשתמש ב- ooverlapped לפחות לפי מה שהבנתי מהתיעוד.
חשבתי ליצור map שה- key הוא threadid וה- value הוא ה- event handler
ואז לקרוא לו מה- callback
 
מעניין, באמת שנראה שבפונקציה הזו אין כזה טוב, אז כמו שאמר טרול, אין לך ברירה אלא להשתמש בפונקציה סטטית שקוראת באופן hard-coded למתודה באובייקט הספציפי שלך. אם יש לך רק אובייקט אחד כזה, זו לא בעיה. אם יש הרבה, תצטרכי איזשהו מיפוי או אמצעי אחר שיחזיר לך מצביע לאובייקט שאת צריכה. אין כאן פתרון כללי, תצטרכי לתפור משהו שמתאים למקרה שלך.
 
תודה ותגובה

האם תוכל לתת דוגמא מה הכוונה שקוראת באופן hard-coded למתודה באובייקט הספציפי שלך?
במקרה של מדובר ב -mutltithreading כלומר כמה אובייקטים. לא כל כך הבנתי איך לפתור את זה ע"י מיפוי?
 

selalerer

New member
כל אובייקט קורא בעצמו ל-MQReceiveMessage?

אם כן (ואני חושב שכך צריך להיות) אז הוא יכול להעביר את ה-MQMSGPROPS עם תוכן שהוא רוצה (בין השאר פויינטר ל-this) ואז ב-callback לקבל את זה כל פעם כשמגיעה הודעה, להמיר לאובייקט ולקרוא למטודה של האובייקט (איזשהו onMessageReceived או משהו כזה).



כל זה לא קשור ישירות ל-thread safety.

התיעוד שם לא אומר מפורשות האם ה-callback יקרא מכמה threadים או לא, מה שכן כתוב זה:


"you can register only 63 callbacks at the same time. Internally, Message Queuing uses the WaitForMultipleObjects API"

זה רומז שכל ה-callbackים ל-message queues נקראים מאותו thread אבל יכול להיות שפנימית זה ממומש בצורה שונה (למשל בעזרת thread pool). את יכולה לעשות ניסויים.

אני מניח שאם ה-message queue מחוייב לשמירה על סדר, אין הרבה הגיון לקרוא ל-callbackים של אותו message queue במקביל לשתי הודעות שונות, זה מקשה מאוד על האפליקציה לשמור על סדר (עד כדי בלתי אפשרי).
 
במימוש הנוכחי

נקרא MQReceiveMessage מכל thread. הקריאה נעשית מול מתודה ב- class

איך להעביר this בעזרת MQMSGPROPS?

לא כל כך הבנתי את ההסבר האחרון. אתה מתכוון לגביי המימוש של MQReceiveMessage?
הקריאה נעשית בכמה threads כי המטרה לבדוק (PEEK) האם קיימת הודעה בתור. אם כן אז (ב- thread) לעלות אובייקט אחר ששולף ומטפל בהודעה.
למיטה ידיעתי MQReceiveMessage עצמו הוא כן thread-safe
 
למעלה