root/OpenSceneGraph/trunk/src/OpenThreads/win32/Win32ConditionPrivateData.h @ 9958

Revision 9958, 4.0 kB (checked in by robert, 5 years ago)

From Csaba Halasz, "IIRC the C++ standard says members will be initialized in declaration
order, and not in the order they are listed in the constructor. To
avoid possible trouble, gcc warns about this. Attached modification
fixes the initializer order to silence this warning."

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007  The Open Thread Group
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14//
15//
16// WIN32ConditionPrivateData.h - Private data structure for Condition
17// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18//
19#ifndef _WIN32CONDITIONPRIVATEDATA_H_
20#define _WIN32CONDITIONPRIVATEDATA_H_
21
22#ifndef _WINDOWS_
23#define WIN32_LEAN_AND_MEAN
24#define _WIN32_WINNT 0x0400
25#include <windows.h>
26#endif
27
28#include <OpenThreads/ScopedLock>
29
30#include "Win32ThreadPrivateData.h"
31#include "HandleHolder.h"
32
33#define InterlockedGet(x) InterlockedExchangeAdd(x,0)
34
35namespace OpenThreads {
36
37class Condition;
38
39class Win32ConditionPrivateData {
40public:
41    friend class Condition;
42    /// number of waiters.
43    long waiters_;
44
45    Win32ConditionPrivateData ()
46        :waiters_(0),
47         sema_(CreateSemaphore(NULL,0,0x7fffffff,NULL)),
48         waiters_done_(CreateEvent(NULL,FALSE,FALSE,NULL)),
49         was_broadcast_(0)
50    {
51    }
52
53    ~Win32ConditionPrivateData ();
54
55    inline int broadcast ()
56    {
57        int have_waiters = 0;
58        long w = InterlockedGet(&waiters_);
59
60        if (w > 0)
61        {
62          // we are broadcasting. 
63          was_broadcast_ = 1;
64          have_waiters = 1;
65        }
66
67        int result = 0;
68        if (have_waiters)
69        {
70            // Wake up all the waiters.
71            ReleaseSemaphore(sema_.get(),waiters_,NULL);
72
73            cooperativeWait(waiters_done_.get(), INFINITE);
74
75            //end of broadcasting
76            was_broadcast_ = 0;
77        }
78        return result;
79    }
80
81    inline int signal()
82    {
83        long w = InterlockedGet(&waiters_);
84        int have_waiters = w > 0;
85 
86        int result = 0;
87
88        if (have_waiters)
89        {
90            if( !ReleaseSemaphore(sema_.get(),1,NULL) )
91                result = -1;
92        }
93        return result;
94    }
95
96    inline int wait (Mutex& external_mutex, long timeout_ms)
97    {
98   
99        // Prevent race conditions on the <waiters_> count.
100        InterlockedIncrement(&waiters_);
101
102        int result = 0;
103
104        ReverseScopedLock<Mutex> lock(external_mutex);
105
106        // wait in timeslices, giving testCancel() a change to
107        // exit the thread if requested.
108        try {
109              DWORD dwResult = cooperativeWait(sema_.get(), timeout_ms);
110            if(dwResult != WAIT_OBJECT_0)
111                result = (int)dwResult;
112        }
113        catch(...){
114            // thread is canceled in cooperative wait , do cleanup
115            InterlockedDecrement(&waiters_);
116            long w = InterlockedGet(&waiters_);
117            int last_waiter = was_broadcast_ && w == 0;
118
119            if (last_waiter)  SetEvent(waiters_done_.get());
120            // rethrow
121            throw;
122        }
123
124       
125        // We're ready to return, so there's one less waiter.
126        InterlockedDecrement(&waiters_);
127        long w = InterlockedGet(&waiters_);
128        int last_waiter = was_broadcast_ && w == 0;
129
130        if (result != -1 && last_waiter)
131            SetEvent(waiters_done_.get());
132
133        return result;
134    }
135
136protected:
137
138  /// Serialize access to the waiters count.
139  /// Mutex waiters_lock_;
140  /// Queue up threads waiting for the condition to become signaled.
141  HandleHolder sema_;
142  /**
143   * An auto reset event used by the broadcast/signal thread to wait
144   * for the waiting thread(s) to wake up and get a chance at the
145   * semaphore.
146   */
147  HandleHolder waiters_done_;
148  /// Keeps track of whether we were broadcasting or just signaling.
149  size_t was_broadcast_;
150};
151
152#undef InterlockedGet
153
154}
155
156
157
158
159
160
161
162#endif // !_WIN32CONDITIONPRIVATEDATA_H_
163
164
Note: See TracBrowser for help on using the browser.