1 /*****************************************************************
2 |
3 | Neptune - Threads
4 |
5 | Copyright (c) 2002-2008, Axiomatic Systems, LLC.
6 | All rights reserved.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 | * Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | notice, this list of conditions and the following disclaimer in the
14 | documentation and/or other materials provided with the distribution.
15 | * Neither the name of Axiomatic Systems nor the
16 | names of its contributors may be used to endorse or promote products
17 | derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 ****************************************************************/
31
32 /*----------------------------------------------------------------------
33 | includes
34 +---------------------------------------------------------------------*/
35 #include "NptThreads.h"
36
37 /*----------------------------------------------------------------------
38 | NPT_SingletonLock
39 +---------------------------------------------------------------------*/
40 NPT_Mutex NPT_SingletonLock::Instance;
41
42 /*----------------------------------------------------------------------
43 | NPT_ThreadCallbackSlot::NPT_ThreadCallbackSlot
44 +---------------------------------------------------------------------*/
NPT_ThreadCallbackSlot()45 NPT_ThreadCallbackSlot::NPT_ThreadCallbackSlot() :
46 m_CallbackArgs(NULL),
47 m_Shutdown(false),
48 m_NotificationHelper(NULL)
49 {
50 }
51
52 /*----------------------------------------------------------------------
53 | NPT_ThreadCallbackSlot::Shutdown
54 +---------------------------------------------------------------------*/
55 NPT_Result
Shutdown()56 NPT_ThreadCallbackSlot::Shutdown()
57 {
58 // protect against concurrent access
59 //FIXME: This will not work if another Thread has called ReceiveCallback with a timeout
60 NPT_AutoLock lock(m_ReadLock);
61
62 // signal we are shut down
63 m_Shutdown = true;
64
65 // clear up any pending callbacks
66 m_Pending.SetValue(0);
67 m_Ack.SetValue(1);
68
69 return NPT_SUCCESS;
70 }
71
72 /*----------------------------------------------------------------------
73 | NPT_ThreadCallbackSlot::SetNotificationHelper
74 +---------------------------------------------------------------------*/
75 NPT_Result
SetNotificationHelper(NotificationHelper * helper)76 NPT_ThreadCallbackSlot::SetNotificationHelper(NotificationHelper* helper)
77 {
78 m_NotificationHelper = helper;
79 return NPT_SUCCESS;
80 }
81
82 /*----------------------------------------------------------------------
83 | NPT_ThreadCallbackSlot::ReceiveCallback
84 +---------------------------------------------------------------------*/
85 NPT_Result
ReceiveCallback(NPT_ThreadCallbackReceiver & receiver,NPT_Timeout timeout)86 NPT_ThreadCallbackSlot::ReceiveCallback(NPT_ThreadCallbackReceiver& receiver,
87 NPT_Timeout timeout)
88 {
89 // protect against concurrent access
90 //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - read locking, timeout=%d\n", timeout);
91 NPT_AutoLock lock(m_ReadLock);
92
93 if (timeout) {
94 // wait until there is a pending callback
95 //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - waiting...\n");
96 NPT_Result result = m_Pending.WaitUntilEquals(1, timeout);
97 if (NPT_FAILED(result)) return result; // don't log here because the result
98 // could be NPT_ERROR_TIMEOUT which
99 // is an expected normal case.
100 //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - got it\n");
101 } else {
102 // see if something is pending
103 if (m_Pending.GetValue() == 0) {
104 //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - nothing pending\n");
105 return NPT_ERROR_CALLBACK_NOTHING_PENDING;
106 }
107 }
108
109 // check if we have been shutdown
110 if (m_Shutdown) return NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN;
111
112 // process the callback
113 //NPT_Debug("NPT_ThreadCallbackSlot::ReceiveCallback - calling back\n");
114 receiver.OnCallback(const_cast<void*>(m_CallbackArgs));
115
116 // signal that we've processed the callback
117 m_Pending.SetValue(0);
118 m_Ack.SetValue(1);
119
120 return NPT_SUCCESS;
121 }
122
123 /*----------------------------------------------------------------------
124 | NPT_ThreadCallbackSlot::SendCallback
125 +---------------------------------------------------------------------*/
126 NPT_Result
SendCallback(void * args)127 NPT_ThreadCallbackSlot::SendCallback(void* args)
128 {
129 // protect against concurrent access
130 //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - write locking\n");
131 NPT_AutoLock lock(m_WriteLock);
132
133 // there should be nothing pending
134 #if defined(NPT_DEBUG)
135 NPT_ASSERT(m_Pending.GetValue() == 0);
136 #endif
137
138 // check if we have been shutdown
139 if (m_Shutdown) return NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN;
140
141 // put the callback args
142 m_CallbackArgs = args;
143 //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - signalling\n");
144 m_Pending.SetValue(1);
145
146 // call the helper before we wait
147 if (m_NotificationHelper) {
148 m_NotificationHelper->Notify();
149 }
150
151 // wait until the callback has been process, or we've been shutdown
152 //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - waiting...\n");
153 m_Ack.WaitUntilEquals(1);
154 //NPT_Debug("NPT_ThreadCallbackSlot::SendCallback - got it\n");
155
156 // done
157 m_Ack.SetValue(0);
158 m_CallbackArgs = NULL;
159
160 return m_Shutdown?NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN:NPT_SUCCESS;
161 }
162