merged: Platinum from linuxport branches
[xbmc:xbmc-antiquated.git] / xbmc / lib / libUPnP / Platinum / ThirdParty / Neptune / Source / Core / NptThreads.cpp
1 /*****************************************************************\r
2 |\r
3 |   Neptune - Threads\r
4 |\r
5 |   (c) 2001-2006 Gilles Boccon-Gibod\r
6 |   Author: Gilles Boccon-Gibod (bok@bok.net)\r
7 |\r
8  ****************************************************************/\r
9 \r
10 /*----------------------------------------------------------------------\r
11 |   includes\r
12 +---------------------------------------------------------------------*/\r
13 #include "NptThreads.h"\r
14 \r
15 /*----------------------------------------------------------------------\r
16 |   NPT_ThreadCallbackSlot::NPT_ThreadCallbackSlot\r
17 +---------------------------------------------------------------------*/\r
18 NPT_ThreadCallbackSlot::NPT_ThreadCallbackSlot() :\r
19     m_CallbackArgs(NULL),\r
20     m_Shutdown(false),\r
21     m_NotificationHelper(NULL)\r
22 {\r
23 }\r
24 \r
25 /*----------------------------------------------------------------------\r
26 |   NPT_ThreadCallbackSlot::Shutdown\r
27 +---------------------------------------------------------------------*/\r
28 NPT_Result \r
29 NPT_ThreadCallbackSlot::Shutdown()\r
30 {\r
31     // protect against concurrent access\r
32     //FIXME: This will not work if another Thread has called ReceiveCallback with a timeout\r
33     NPT_AutoLock lock(m_ReadLock);\r
34 \r
35     // signal we are shut down\r
36     m_Shutdown = true;\r
37 \r
38     // clear up any pending callbacks\r
39     m_Pending.SetValue(0);\r
40     m_Ack.SetValue(1);\r
41 \r
42     return NPT_SUCCESS;\r
43 }\r
44 \r
45 /*----------------------------------------------------------------------\r
46 |   NPT_ThreadCallbackSlot::SetNotificationHelper\r
47 +---------------------------------------------------------------------*/\r
48 NPT_Result \r
49 NPT_ThreadCallbackSlot::SetNotificationHelper(NotificationHelper* helper)\r
50 {\r
51     m_NotificationHelper = helper;\r
52     return NPT_SUCCESS;\r
53 }\r
54 \r
55 /*----------------------------------------------------------------------\r
56 |   NPT_ThreadCallbackSlot::ReceiveCallback\r
57 +---------------------------------------------------------------------*/\r
58 NPT_Result \r
59 NPT_ThreadCallbackSlot::ReceiveCallback(NPT_ThreadCallbackReceiver& receiver,\r
60                                         NPT_Timeout                 timeout)\r
61 {\r
62     // protect against concurrent access\r
63     //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - read locking, timeout=%d\n", timeout);\r
64     NPT_AutoLock lock(m_ReadLock);\r
65 \r
66     if (timeout) {\r
67         // wait until there is a pending callback\r
68         //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - waiting...\n");\r
69         NPT_Result result = m_Pending.WaitUntilEquals(1, timeout);\r
70         if (NPT_FAILED(result)) return result; // don't log here because the result\r
71                                                // could be NPT_ERROR_TIMEOUT which\r
72                                                // is an expected normal case.\r
73         //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - got it\n");\r
74     } else {\r
75         // see if something is pending\r
76         if (m_Pending.GetValue() == 0) {\r
77             //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - nothing pending\n");\r
78             return NPT_ERROR_CALLBACK_NOTHING_PENDING;\r
79         }\r
80     }\r
81 \r
82     // check if we have been shutdown\r
83     if (m_Shutdown) return NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN;\r
84 \r
85     // process the callback\r
86     //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - calling back\n");\r
87     receiver.OnCallback(const_cast<void*>(m_CallbackArgs));\r
88 \r
89     // signal that we've processed the callback\r
90     m_Pending.SetValue(0);\r
91     m_Ack.SetValue(1);\r
92 \r
93     return NPT_SUCCESS;\r
94 }\r
95 \r
96 /*----------------------------------------------------------------------\r
97 |   NPT_ThreadCallbackSlot::SendCallback\r
98 +---------------------------------------------------------------------*/\r
99 NPT_Result \r
100 NPT_ThreadCallbackSlot::SendCallback(void* args)\r
101 {\r
102     // protect against concurrent access\r
103     //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - write locking\n");\r
104     NPT_AutoLock lock(m_WriteLock);\r
105 \r
106     // there should be nothing pending\r
107 #if defined(NPT_DEBUG)\r
108     NPT_ASSERT(m_Pending.GetValue() == 0);\r
109 #endif\r
110 \r
111     // check if we have been shutdown\r
112     if (m_Shutdown) return NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN;\r
113 \r
114     // put the callback args\r
115     m_CallbackArgs = args;\r
116     //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - signalling\n");\r
117     m_Pending.SetValue(1);\r
118     \r
119     // call the helper before we wait\r
120     if (m_NotificationHelper) {\r
121         m_NotificationHelper->Notify();\r
122     }\r
123 \r
124     // wait until the callback has been process, or we've been shutdown\r
125     //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - waiting...\n");\r
126     m_Ack.WaitUntilEquals(1);\r
127     //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - got it\n");\r
128 \r
129     // done\r
130     m_Ack.SetValue(0);\r
131     m_CallbackArgs = NULL;\r
132 \r
133     return m_Shutdown?NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN:NPT_SUCCESS;\r
134 }\r