~armagetronad-dev/armagetronad/trunk-winlibs-work

« back to all changes in this revision

Viewing changes to boost/includes/boost/thread/win32/basic_timed_mutex.hpp

  • Committer: Manuel Moos
  • Date: 2011-08-25 10:46:34 UTC
  • Revision ID: manuel@moosnet.de-20110825104634-60a1qoe9tnpkc3ov
Adding boost::thread part 3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
 
2
#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
 
3
 
 
4
//  basic_timed_mutex_win32.hpp
 
5
//
 
6
//  (C) Copyright 2006-8 Anthony Williams 
 
7
//
 
8
//  Distributed under the Boost Software License, Version 1.0. (See
 
9
//  accompanying file LICENSE_1_0.txt or copy at
 
10
//  http://www.boost.org/LICENSE_1_0.txt)
 
11
 
 
12
#include <boost/assert.hpp>
 
13
#include "thread_primitives.hpp"
 
14
#include "interlocked_read.hpp"
 
15
#include <boost/thread/thread_time.hpp>
 
16
#include <boost/thread/xtime.hpp>
 
17
#include <boost/detail/interlocked.hpp>
 
18
 
 
19
#include <boost/config/abi_prefix.hpp>
 
20
 
 
21
namespace boost
 
22
{
 
23
    namespace detail
 
24
    {
 
25
        struct basic_timed_mutex
 
26
        {
 
27
            BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31);
 
28
            BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30);
 
29
            BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit);
 
30
            BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit);
 
31
            long active_count;
 
32
            void* event;
 
33
 
 
34
            void initialize()
 
35
            {
 
36
                active_count=0;
 
37
                event=0;
 
38
            }
 
39
 
 
40
            void destroy()
 
41
            {
 
42
#ifdef BOOST_MSVC
 
43
#pragma warning(push)
 
44
#pragma warning(disable:4312)
 
45
#endif
 
46
                void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0);
 
47
#ifdef BOOST_MSVC
 
48
#pragma warning(pop)
 
49
#endif
 
50
                if(old_event)
 
51
                {
 
52
                    win32::CloseHandle(old_event);
 
53
                }
 
54
            }
 
55
            
 
56
          
 
57
            bool try_lock()
 
58
            {
 
59
                return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
 
60
            }
 
61
            
 
62
            void lock()
 
63
            {
 
64
                if(try_lock())
 
65
                {
 
66
                    return;
 
67
                }
 
68
                long old_count=active_count;
 
69
                mark_waiting_and_try_lock(old_count);
 
70
 
 
71
                if(old_count&lock_flag_value)
 
72
                {
 
73
                    bool lock_acquired=false;
 
74
                    void* const sem=get_event();
 
75
 
 
76
                    do
 
77
                    {
 
78
                        BOOST_VERIFY(win32::WaitForSingleObject(
 
79
                                         sem,::boost::detail::win32::infinite)==0);
 
80
                        clear_waiting_and_try_lock(old_count);
 
81
                        lock_acquired=!(old_count&lock_flag_value);
 
82
                    }
 
83
                    while(!lock_acquired);
 
84
                }
 
85
            }
 
86
            void mark_waiting_and_try_lock(long& old_count)
 
87
            {
 
88
                for(;;)
 
89
                {
 
90
                    long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
 
91
                    long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
 
92
                    if(current==old_count)
 
93
                    {
 
94
                        break;
 
95
                    }
 
96
                    old_count=current;
 
97
                }
 
98
            }
 
99
 
 
100
            void clear_waiting_and_try_lock(long& old_count)
 
101
            {
 
102
                old_count&=~lock_flag_value;
 
103
                old_count|=event_set_flag_value;
 
104
                for(;;)
 
105
                {
 
106
                    long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
 
107
                    long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
 
108
                    if(current==old_count)
 
109
                    {
 
110
                        break;
 
111
                    }
 
112
                    old_count=current;
 
113
                }
 
114
            }
 
115
            
 
116
            
 
117
            bool timed_lock(::boost::system_time const& wait_until)
 
118
            {
 
119
                if(try_lock())
 
120
                {
 
121
                    return true;
 
122
                }
 
123
                long old_count=active_count;
 
124
                mark_waiting_and_try_lock(old_count);
 
125
 
 
126
                if(old_count&lock_flag_value)
 
127
                {
 
128
                    bool lock_acquired=false;
 
129
                    void* const sem=get_event();
 
130
 
 
131
                    do
 
132
                    {
 
133
                        if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
 
134
                        {
 
135
                            BOOST_INTERLOCKED_DECREMENT(&active_count);
 
136
                            return false;
 
137
                        }
 
138
                        clear_waiting_and_try_lock(old_count);
 
139
                        lock_acquired=!(old_count&lock_flag_value);
 
140
                    }
 
141
                    while(!lock_acquired);
 
142
                }
 
143
                return true;
 
144
            }
 
145
 
 
146
            template<typename Duration>
 
147
            bool timed_lock(Duration const& timeout)
 
148
            {
 
149
                return timed_lock(get_system_time()+timeout);
 
150
            }
 
151
 
 
152
            bool timed_lock(boost::xtime const& timeout)
 
153
            {
 
154
                return timed_lock(system_time(timeout));
 
155
            }
 
156
 
 
157
            void unlock()
 
158
            {
 
159
                long const offset=lock_flag_value;
 
160
                long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
 
161
                if(!(old_count&event_set_flag_value) && (old_count>offset))
 
162
                {
 
163
                    if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
 
164
                    {
 
165
                        win32::SetEvent(get_event());
 
166
                    }
 
167
                }
 
168
            }
 
169
 
 
170
        private:
 
171
            void* get_event()
 
172
            {
 
173
                void* current_event=::boost::detail::interlocked_read_acquire(&event);
 
174
                
 
175
                if(!current_event)
 
176
                {
 
177
                    void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
 
178
#ifdef BOOST_MSVC
 
179
#pragma warning(push)
 
180
#pragma warning(disable:4311)
 
181
#pragma warning(disable:4312)
 
182
#endif
 
183
                    void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
 
184
#ifdef BOOST_MSVC
 
185
#pragma warning(pop)
 
186
#endif
 
187
                    if(old_event!=0)
 
188
                    {
 
189
                        win32::CloseHandle(new_event);
 
190
                        return old_event;
 
191
                    }
 
192
                    else
 
193
                    {
 
194
                        return new_event;
 
195
                    }
 
196
                }
 
197
                return current_event;
 
198
            }
 
199
            
 
200
        };
 
201
        
 
202
    }
 
203
}
 
204
 
 
205
#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
 
206
 
 
207
#include <boost/config/abi_suffix.hpp>
 
208
 
 
209
#endif