Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/thread/detail/read_write_lock.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 31.2 KB
Line 
1// Copyright (C)  2002-2003
2// David Moore, Michael Glassford
3//
4// Original scoped_lock implementation
5// Copyright (C) 2001
6// William E. Kempf
7//
8//  Distributed under the Boost Software License, Version 1.0. (See accompanying
9//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10
11#ifndef BOOST_READ_WRITE_LOCK_JDM031002_HPP
12#define BOOST_READ_WRITE_LOCK_JDM031002_HPP
13
14#include <boost/thread/detail/config.hpp>
15
16#include <boost/utility.hpp>
17#include <boost/thread/exceptions.hpp>
18#include <boost/thread/detail/lock.hpp>
19
20namespace boost {
21
22struct xtime;
23
24namespace read_write_lock_state {
25    enum read_write_lock_state_enum
26    {
27        unlocked=0,
28        read_locked=1,
29        write_locked=2
30    };
31} //namespace read_write_lock_state
32
33namespace detail {
34namespace thread {
35
36template <typename Mutex>
37class read_write_lock_ops : private noncopyable
38{
39private:
40
41    read_write_lock_ops() { }
42    ~read_write_lock_ops() { }
43
44public:
45
46    typedef Mutex mutex_type;
47
48    static void write_lock(Mutex& m)
49    {
50        m.do_write_lock();
51    }
52    static void read_lock(Mutex& m)
53    {
54        m.do_read_lock();
55    }
56    static void write_unlock(Mutex& m)
57    {
58        m.do_write_unlock();
59    }
60    static void read_unlock(Mutex &m)
61    {
62        m.do_read_unlock();
63    }
64    static bool try_write_lock(Mutex &m)
65    {
66        return m.do_try_write_lock();
67    }
68    static bool try_read_lock(Mutex &m)
69    {
70        return m.do_try_read_lock();
71    }
72
73    static bool timed_write_lock(Mutex &m,const xtime &xt)
74    {
75        return m.do_timed_write_lock(xt);
76    }
77    static bool timed_read_lock(Mutex &m,const xtime &xt)
78    {
79        return m.do_timed_read_lock(xt);
80    }
81
82    static void demote(Mutex & m)
83    {
84        m.do_demote_to_read_lock();
85    }
86    static bool try_demote(Mutex & m)
87    {
88        return m.do_try_demote_to_read_lock();
89    }
90    static bool timed_demote(Mutex & m,const xtime &xt)
91    {
92        return m.do_timed_demote_to_read_lock(xt);
93    }
94
95    static void promote(Mutex & m)
96    {
97        m.do_promote_to_write_lock();
98    }
99    static bool try_promote(Mutex & m)
100    {
101        return m.do_try_promote_to_write_lock();
102    }
103    static bool timed_promote(Mutex & m,const xtime &xt)
104    {
105        return m.do_timed_promote_to_write_lock(xt);
106    }
107};
108
109template <typename ReadWriteMutex>
110class scoped_read_write_lock : private noncopyable
111{
112public:
113
114    typedef ReadWriteMutex mutex_type;
115
116    scoped_read_write_lock(
117        ReadWriteMutex& mx,
118        read_write_lock_state::read_write_lock_state_enum initial_state)
119        : m_mutex(mx), m_state(read_write_lock_state::unlocked)
120    {
121        if (initial_state == read_write_lock_state::read_locked)
122            read_lock();
123        else if (initial_state == read_write_lock_state::write_locked)
124            write_lock();
125    }
126
127    ~scoped_read_write_lock()
128    {
129        if (m_state != read_write_lock_state::unlocked)
130            unlock();
131    }
132
133    void read_lock()
134    {
135        if (m_state != read_write_lock_state::unlocked) throw lock_error();
136        read_write_lock_ops<ReadWriteMutex>::read_lock(m_mutex);
137        m_state = read_write_lock_state::read_locked;
138    }
139
140    void write_lock()
141    {
142        if (m_state != read_write_lock_state::unlocked) throw lock_error();
143        read_write_lock_ops<ReadWriteMutex>::write_lock(m_mutex);
144        m_state = read_write_lock_state::write_locked;
145    }
146
147    void unlock()
148    {
149        if (m_state == read_write_lock_state::unlocked) throw lock_error();
150        if (m_state == read_write_lock_state::read_locked)
151            read_write_lock_ops<ReadWriteMutex>::read_unlock(m_mutex);
152        else //(m_state == read_write_lock_state::write_locked)
153            read_write_lock_ops<ReadWriteMutex>::write_unlock(m_mutex);
154
155        m_state = read_write_lock_state::unlocked;
156    }
157
158    void demote(void)
159    {
160        if (m_state != read_write_lock_state::write_locked) throw lock_error();
161        read_write_lock_ops<ReadWriteMutex>::demote(m_mutex);
162        m_state = read_write_lock_state::read_locked;
163    }
164
165    void promote(void)
166    {
167        if (m_state != read_write_lock_state::read_locked) throw lock_error();
168        read_write_lock_ops<ReadWriteMutex>::promote(m_mutex);
169        m_state = read_write_lock_state::write_locked;
170    }
171
172    //If allow_unlock = true, set_lock always succeeds and
173    //the function result indicates whether an unlock was required.
174    //If allow_unlock = false, set_lock may fail;
175    //the function result indicates whether it succeeded.
176    bool set_lock(read_write_lock_state::read_write_lock_state_enum ls, bool allow_unlock = true)
177    {
178        bool result = !allow_unlock;
179
180        if (m_state != ls)
181        {
182            if (m_state == read_write_lock_state::unlocked)
183            {
184                if (ls == read_write_lock_state::read_locked)
185                    read_lock();
186                else //(ls == read_write_lock_state::write_locked)
187                    write_lock();
188            }
189            else //(m_state == read_write_lock_state::read_locked || m_state == read_write_lock_state::write_locked)
190            {
191                if (ls == read_write_lock_state::read_locked)
192                    demote();
193                else if (ls == read_write_lock_state::write_locked)
194                {
195                    if (allow_unlock)
196                    {
197                        result = true;
198                        unlock();
199                        write_lock();
200                    }
201                    else
202                        result = false;
203                }
204                else //(ls == read_write_lock_state::unlocked)
205                    unlock();
206            }
207        }
208
209        return result;
210    }
211 
212    bool locked() const
213    {
214        return m_state != read_write_lock_state::unlocked;
215    }
216 
217    bool read_locked() const
218    {
219        return m_state == read_write_lock_state::read_locked;
220    }
221 
222    bool write_locked() const
223    {
224        return m_state != read_write_lock_state::write_locked;
225    }
226
227    operator const void*() const
228    {
229        return (m_state != read_write_lock_state::unlocked) ? this : 0; 
230    }
231
232    read_write_lock_state::read_write_lock_state_enum state() const
233    {
234        return m_state;
235    }
236   
237private:
238
239    ReadWriteMutex& m_mutex;
240    read_write_lock_state::read_write_lock_state_enum m_state;
241};
242
243template <typename ReadWriteMutex>
244class scoped_read_lock : private noncopyable
245{
246public:
247
248    typedef ReadWriteMutex mutex_type;
249
250    explicit scoped_read_lock(
251        ReadWriteMutex& mx,
252        bool initially_locked = true)
253        : m_mutex(mx), m_state(read_write_lock_state::unlocked)
254    {
255        if (initially_locked)
256            lock();
257    }
258
259    ~scoped_read_lock()
260    {
261        if (m_state != read_write_lock_state::unlocked)
262            unlock();
263    }
264
265    void lock()
266    {
267        if (m_state != read_write_lock_state::unlocked) throw lock_error();
268        read_write_lock_ops<ReadWriteMutex>::read_lock(m_mutex);
269        m_state = read_write_lock_state::read_locked;
270    }
271
272    void unlock()
273    {
274        if (m_state != read_write_lock_state::read_locked) throw lock_error();
275        read_write_lock_ops<ReadWriteMutex>::read_unlock(m_mutex);
276
277        m_state = read_write_lock_state::unlocked;
278    }
279 
280    bool locked() const
281    {
282        return m_state != read_write_lock_state::unlocked;
283    }
284
285    operator const void*() const
286    {
287        return (m_state != read_write_lock_state::unlocked) ? this : 0; 
288    }
289   
290private:
291
292    ReadWriteMutex& m_mutex;
293    read_write_lock_state::read_write_lock_state_enum m_state;
294};
295
296template <typename ReadWriteMutex>
297class scoped_write_lock : private noncopyable
298{
299public:
300
301    typedef ReadWriteMutex mutex_type;
302
303    explicit scoped_write_lock(
304        ReadWriteMutex& mx,
305        bool initially_locked = true)
306        : m_mutex(mx), m_state(read_write_lock_state::unlocked)
307    {
308        if (initially_locked)
309            lock();
310    }
311
312    ~scoped_write_lock()
313    {
314        if (m_state != read_write_lock_state::unlocked)
315            unlock();
316    }
317
318    void lock()
319    {
320        if (m_state != read_write_lock_state::unlocked) throw lock_error();
321        read_write_lock_ops<ReadWriteMutex>::write_lock(m_mutex);
322        m_state = read_write_lock_state::write_locked;
323    }
324
325    void unlock()
326    {
327        if (m_state != read_write_lock_state::write_locked) throw lock_error();
328        read_write_lock_ops<ReadWriteMutex>::write_unlock(m_mutex);
329
330        m_state = read_write_lock_state::unlocked;
331    }
332 
333    bool locked() const
334    {
335        return m_state != read_write_lock_state::unlocked;
336    }
337
338    operator const void*() const
339    {
340        return (m_state != read_write_lock_state::unlocked) ? this : 0; 
341    }
342   
343private:
344
345    ReadWriteMutex& m_mutex;
346    read_write_lock_state::read_write_lock_state_enum m_state;
347};
348
349template <typename TryReadWriteMutex>
350class scoped_try_read_write_lock : private noncopyable
351{
352public:
353
354    typedef TryReadWriteMutex mutex_type;
355   
356    scoped_try_read_write_lock(
357        TryReadWriteMutex& mx,
358        read_write_lock_state::read_write_lock_state_enum initial_state)
359        : m_mutex(mx), m_state(read_write_lock_state::unlocked)
360    {
361        if (initial_state == read_write_lock_state::read_locked)
362            read_lock();
363        else if (initial_state == read_write_lock_state::write_locked)
364            write_lock();
365    }
366
367    ~scoped_try_read_write_lock()
368    {
369        if (m_state != read_write_lock_state::unlocked)
370            unlock();
371    }
372
373    void read_lock()
374    {
375        if (m_state != read_write_lock_state::unlocked) throw lock_error();
376        read_write_lock_ops<TryReadWriteMutex>::read_lock(m_mutex);
377        m_state = read_write_lock_state::read_locked;
378    }
379
380    bool try_read_lock()
381    {
382        if (m_state != read_write_lock_state::unlocked) throw lock_error();
383        if(read_write_lock_ops<TryReadWriteMutex>::try_read_lock(m_mutex))
384        {
385            m_state = read_write_lock_state::read_locked;
386            return true;
387        }
388        return false;
389    }
390   
391    void write_lock()
392    {
393        if (m_state != read_write_lock_state::unlocked) throw lock_error();
394        read_write_lock_ops<TryReadWriteMutex>::write_lock(m_mutex);
395        m_state = read_write_lock_state::write_locked;
396    }
397
398    bool try_write_lock()
399    {
400        if (m_state != read_write_lock_state::unlocked) throw lock_error();
401        if(read_write_lock_ops<TryReadWriteMutex>::try_write_lock(m_mutex))
402        {
403            m_state = read_write_lock_state::write_locked;
404            return true;
405        }
406        return false;
407    }
408
409    void unlock()
410    {
411        if (m_state == read_write_lock_state::unlocked) throw lock_error();
412        if (m_state == read_write_lock_state::read_locked)
413            read_write_lock_ops<TryReadWriteMutex>::read_unlock(m_mutex);
414        else //(m_state == read_write_lock_state::write_locked)
415            read_write_lock_ops<TryReadWriteMutex>::write_unlock(m_mutex);
416
417        m_state = read_write_lock_state::unlocked;
418    }
419
420    void demote(void)
421    {
422        if (m_state != read_write_lock_state::write_locked) throw lock_error();
423        read_write_lock_ops<TryReadWriteMutex>::demote(m_mutex);
424        m_state = read_write_lock_state::read_locked;
425    }
426
427    bool try_demote(void)
428    {
429        if (m_state != read_write_lock_state::write_locked) throw lock_error();
430        return read_write_lock_ops<TryReadWriteMutex>::try_demote(m_mutex) ? (m_state = read_write_lock_state::read_locked, true) : false;
431    }
432
433    void promote(void)
434    {
435        if (m_state != read_write_lock_state::read_locked) throw lock_error();
436        read_write_lock_ops<TryReadWriteMutex>::promote(m_mutex);
437        m_state = read_write_lock_state::write_locked;
438    }
439
440    bool try_promote(void)
441    {
442        if (m_state != read_write_lock_state::read_locked) throw lock_error();
443        return read_write_lock_ops<TryReadWriteMutex>::try_promote(m_mutex) ? (m_state = read_write_lock_state::write_locked, true) : false;
444    }
445
446    //If allow_unlock = true, set_lock always succeeds and
447    //the function result indicates whether an unlock was required.
448    //If allow_unlock = false, set_lock may fail;
449    //the function result indicates whether it succeeded.
450    bool set_lock(read_write_lock_state::read_write_lock_state_enum ls, bool allow_unlock = true)
451    {
452        bool result = !allow_unlock;
453
454        if (m_state != ls)
455        {
456            if (m_state == read_write_lock_state::unlocked)
457            {
458                if (ls == read_write_lock_state::read_locked)
459                    read_lock();
460                else //(ls == read_write_lock_state::write_locked)
461                    write_lock();
462            }
463            else //(m_state == read_write_lock_state::read_locked || m_state == read_write_lock_state::write_locked)
464            {
465                if (ls == read_write_lock_state::read_locked)
466                    demote();
467                else if (ls == read_write_lock_state::write_locked)
468                {
469                    if (!try_promote())
470                    {
471                        if (allow_unlock)
472                        {
473                            result = true;
474                            unlock();
475                            write_lock();
476                        }
477                        else
478                            result = false;
479                    }
480                }
481                else //(ls == read_write_lock_state::unlocked)
482                    unlock();
483            }
484        }
485
486        return result;
487    }
488
489    bool try_set_lock(read_write_lock_state::read_write_lock_state_enum ls)
490    {
491        if (m_state != ls)
492        {
493            if (m_state == read_write_lock_state::unlocked)
494            {
495                if (ls == read_write_lock_state::read_locked)
496                    return try_read_lock();
497                else // (ls == read_write_lock_state::write_locked)
498                    return try_write_lock();
499            }
500            else //(m_state == read_write_lock_state::read_locked || m_state == read_write_lock_state::write_locked)
501            {
502                if (ls == read_write_lock_state::read_locked)
503                    return try_demote();
504                else if (ls == read_write_lock_state::write_locked)
505                    return try_promote();
506                else //(ls == read_write_lock_state::unlocked)
507                    return unlock(), true;
508            }
509        }
510        else //(m_state == ls)
511            return true;
512    }
513 
514    bool locked() const
515    {
516        return m_state != read_write_lock_state::unlocked;
517    }
518 
519    bool read_locked() const
520    {
521        return m_state == read_write_lock_state::read_locked;
522    }
523 
524    bool write_locked() const
525    {
526        return m_state != read_write_lock_state::write_locked;
527    }
528
529    operator const void*() const
530    {
531        return (m_state != read_write_lock_state::unlocked) ? this : 0; 
532    }
533
534    read_write_lock_state::read_write_lock_state_enum state() const
535    {
536        return m_state;
537    }
538
539private:
540
541    TryReadWriteMutex& m_mutex;
542    read_write_lock_state::read_write_lock_state_enum m_state;
543};
544
545template <typename TryReadWriteMutex>
546class scoped_try_read_lock : private noncopyable
547{
548public:
549
550    typedef TryReadWriteMutex mutex_type;
551   
552    explicit scoped_try_read_lock(
553        TryReadWriteMutex& mx,
554        bool initially_locked = true)
555        : m_mutex(mx), m_state(read_write_lock_state::unlocked)
556    {
557        if (initially_locked)
558            lock();
559    }
560
561    ~scoped_try_read_lock()
562    {
563        if (m_state != read_write_lock_state::unlocked)
564            unlock();
565    }
566
567    void lock()
568    {
569        if (m_state != read_write_lock_state::unlocked) throw lock_error();
570        read_write_lock_ops<TryReadWriteMutex>::read_lock(m_mutex);
571        m_state = read_write_lock_state::read_locked;
572    }
573
574    bool try_lock()
575    {
576        if (m_state != read_write_lock_state::unlocked) throw lock_error();
577        if(read_write_lock_ops<TryReadWriteMutex>::try_read_lock(m_mutex))
578        {
579            m_state = read_write_lock_state::read_locked;
580            return true;
581        }
582        return false;
583    }
584
585    void unlock()
586    {
587        if (m_state != read_write_lock_state::read_locked) throw lock_error();
588        read_write_lock_ops<TryReadWriteMutex>::read_unlock(m_mutex);
589
590        m_state = read_write_lock_state::unlocked;
591    }
592 
593    bool locked() const
594    {
595        return m_state != read_write_lock_state::unlocked;
596    }
597
598    operator const void*() const
599    {
600        return (m_state != read_write_lock_state::unlocked) ? this : 0; 
601    }
602
603private:
604
605    TryReadWriteMutex& m_mutex;
606    read_write_lock_state::read_write_lock_state_enum m_state;
607};
608
609template <typename TryReadWriteMutex>
610class scoped_try_write_lock : private noncopyable
611{
612public:
613
614    typedef TryReadWriteMutex mutex_type;
615   
616    explicit scoped_try_write_lock(
617        TryReadWriteMutex& mx,
618        bool initially_locked = true)
619        : m_mutex(mx), m_state(read_write_lock_state::unlocked)
620    {
621        if (initially_locked)
622            lock();
623    }
624
625    ~scoped_try_write_lock()
626    {
627        if (m_state != read_write_lock_state::unlocked)
628            unlock();
629    }
630
631    void lock()
632    {
633        if (m_state != read_write_lock_state::unlocked) throw lock_error();
634        read_write_lock_ops<TryReadWriteMutex>::write_lock(m_mutex);
635        m_state = read_write_lock_state::write_locked;
636    }
637
638    bool try_lock()
639    {
640        if (m_state != read_write_lock_state::unlocked) throw lock_error();
641        if(read_write_lock_ops<TryReadWriteMutex>::try_write_lock(m_mutex))
642        {
643            m_state = read_write_lock_state::write_locked;
644            return true;
645        }
646        return false;
647    }
648
649    void unlock()
650    {
651        if (m_state != read_write_lock_state::write_locked) throw lock_error();
652        read_write_lock_ops<TryReadWriteMutex>::write_unlock(m_mutex);
653
654        m_state = read_write_lock_state::unlocked;
655    }
656 
657    bool locked() const
658    {
659        return m_state != read_write_lock_state::unlocked;
660    }
661
662    operator const void*() const
663    {
664        return (m_state != read_write_lock_state::unlocked) ? this : 0; 
665    }
666
667private:
668
669    TryReadWriteMutex& m_mutex;
670    read_write_lock_state::read_write_lock_state_enum m_state;
671};
672
673template <typename TimedReadWriteMutex>
674class scoped_timed_read_write_lock : private noncopyable
675{
676public:
677
678    typedef TimedReadWriteMutex mutex_type;
679
680    scoped_timed_read_write_lock(
681        TimedReadWriteMutex& mx,
682        read_write_lock_state::read_write_lock_state_enum initial_state)
683        : m_mutex(mx), m_state(read_write_lock_state::unlocked)
684    {
685        if (initial_state == read_write_lock_state::read_locked)
686            read_lock();
687        else if (initial_state == read_write_lock_state::write_locked)
688            write_lock();
689    }
690
691    ~scoped_timed_read_write_lock()
692    {
693        if (m_state != read_write_lock_state::unlocked)
694            unlock();
695    }
696
697    void read_lock()
698    {
699        if (m_state != read_write_lock_state::unlocked) throw lock_error();
700        read_write_lock_ops<TimedReadWriteMutex>::read_lock(m_mutex);
701        m_state = read_write_lock_state::read_locked;
702    }
703
704    bool try_read_lock()
705    {
706        if (m_state != read_write_lock_state::unlocked) throw lock_error();
707        if(read_write_lock_ops<TimedReadWriteMutex>::try_read_lock(m_mutex))
708        {
709            m_state = read_write_lock_state::read_locked;
710            return true;
711        }
712        return false;
713    }
714
715    bool timed_read_lock(const xtime &xt)
716    {
717        if (m_state != read_write_lock_state::unlocked) throw lock_error();
718        if(read_write_lock_ops<TimedReadWriteMutex>::timed_read_lock(m_mutex,xt))
719        {
720            m_state = read_write_lock_state::read_locked;
721            return true;
722        }
723        return false;
724    }
725
726    void write_lock()
727    {
728        if (m_state != read_write_lock_state::unlocked) throw lock_error();
729        read_write_lock_ops<TimedReadWriteMutex>::write_lock(m_mutex);
730        m_state = read_write_lock_state::write_locked;
731    }
732
733    bool try_write_lock()
734    {
735        if (m_state != read_write_lock_state::unlocked) throw lock_error();
736        if(read_write_lock_ops<TimedReadWriteMutex>::try_write_lock(m_mutex))
737        {
738            m_state = read_write_lock_state::write_locked;
739            return true;
740        }
741        return false;
742    }
743
744    bool timed_write_lock(const xtime &xt)
745    {
746        if (m_state != read_write_lock_state::unlocked) throw lock_error();
747        if(read_write_lock_ops<TimedReadWriteMutex>::timed_write_lock(m_mutex,xt))
748        {
749            m_state = read_write_lock_state::write_locked;
750            return true;
751        }
752        return false;
753    }
754
755    void unlock()
756    {
757        if (m_state == read_write_lock_state::unlocked) throw lock_error();
758        if (m_state == read_write_lock_state::read_locked)
759            read_write_lock_ops<TimedReadWriteMutex>::read_unlock(m_mutex);
760        else //(m_state == read_write_lock_state::write_locked)
761            read_write_lock_ops<TimedReadWriteMutex>::write_unlock(m_mutex);
762
763        m_state = read_write_lock_state::unlocked;
764    }
765
766    void demote(void)
767    {
768        if (m_state != read_write_lock_state::write_locked) throw lock_error();
769        read_write_lock_ops<TimedReadWriteMutex>::demote(m_mutex);
770        m_state = read_write_lock_state::read_locked;
771    }
772
773    bool try_demote(void)
774    {
775        if (m_state != read_write_lock_state::write_locked) throw lock_error();
776        return read_write_lock_ops<TimedReadWriteMutex>::try_demote(m_mutex) ? (m_state = read_write_lock_state::read_locked, true) : false;
777    }
778
779    bool timed_demote(const xtime &xt)
780    {
781        if (m_state != read_write_lock_state::write_locked) throw lock_error();
782        return read_write_lock_ops<TimedReadWriteMutex>::timed_demote(m_mutex, xt) ? (m_state = read_write_lock_state::read_locked, true) : false;
783    }
784
785    void promote(void)
786    {
787        if (m_state != read_write_lock_state::read_locked) throw lock_error();
788        read_write_lock_ops<TimedReadWriteMutex>::promote(m_mutex);
789        m_state = read_write_lock_state::write_locked;
790    }
791
792    bool try_promote(void)
793    {
794        if (m_state != read_write_lock_state::read_locked) throw lock_error();
795        return read_write_lock_ops<TimedReadWriteMutex>::try_promote(m_mutex) ? (m_state = read_write_lock_state::write_locked, true) : false;
796    }
797
798    bool timed_promote(const xtime &xt)
799    {
800        if (m_state != read_write_lock_state::read_locked) throw lock_error();
801        return read_write_lock_ops<TimedReadWriteMutex>::timed_promote(m_mutex, xt) ? (m_state = read_write_lock_state::write_locked, true) : false;
802    }
803
804    //If allow_unlock = true, set_lock always succeeds and
805    //the function result indicates whether an unlock was required.
806    //If allow_unlock = false, set_lock may fail;
807    //the function result indicates whether it succeeded.
808    bool set_lock(read_write_lock_state::read_write_lock_state_enum ls, bool allow_unlock = true)
809    {
810        bool result = !allow_unlock;
811
812        if (m_state != ls)
813        {
814            if (m_state == read_write_lock_state::unlocked)
815            {
816                if (ls == read_write_lock_state::read_locked)
817                    read_lock();
818                else //(ls == read_write_lock_state::write_locked)
819                    write_lock();
820            }
821            else //(m_state == read_write_lock_state::read_locked || m_state == read_write_lock_state::write_locked)
822            {
823                if (ls == read_write_lock_state::read_locked)
824                    demote();
825                else if (ls == read_write_lock_state::write_locked)
826                {
827                    if (!try_promote())
828                    {
829                        if (allow_unlock)
830                        {
831                            result = true;
832                            unlock();
833                            write_lock();
834                        }
835                        else
836                            result = false;
837                    }
838                }
839                else //(ls == read_write_lock_state::unlocked)
840                    unlock();
841            }
842        }
843
844        return result;
845    }
846
847    bool try_set_lock(read_write_lock_state::read_write_lock_state_enum ls)
848    {
849        if (m_state != ls)
850        {
851            if (m_state == read_write_lock_state::unlocked)
852            {
853                if (ls == read_write_lock_state::read_locked)
854                    return try_read_lock();
855                else // (ls == read_write_lock_state::write_locked)
856                    return try_write_lock();
857            }
858            else //(m_state == read_write_lock_state::read_locked || m_state == read_write_lock_state::write_locked)
859            {
860                if (ls == read_write_lock_state::read_locked)
861                    return try_demote();
862                else if (ls == read_write_lock_state::write_locked)
863                    return try_promote();
864                else //(ls == read_write_lock_state::unlocked)
865                    return unlock(), true;
866            }
867        }
868        else //(m_state == ls)
869            return true;
870    }
871
872    bool timed_set_lock(read_write_lock_state::read_write_lock_state_enum ls, const xtime &xt)
873    {
874        if (m_state != ls)
875        {
876            if (m_state == read_write_lock_state::unlocked)
877            {
878                if (ls == read_write_lock_state::read_locked)
879                    return timed_read_lock(xt);
880                else // (ls == read_write_lock_state::write_locked)
881                    return timed_write_lock(xt);
882            }
883            else //(m_state == read_write_lock_state::read_locked || m_state == read_write_lock_state::write_locked)
884            {
885                if (ls == read_write_lock_state::read_locked)
886                    return timed_demote(xt);
887                else if (ls == read_write_lock_state::write_locked)
888                    return timed_promote(xt);
889                else //(ls == read_write_lock_state::unlocked)
890                    return unlock(), true;
891            }
892        }
893        else //(m_state == ls)
894            return true;
895    }
896 
897    bool locked() const
898    {
899        return m_state != read_write_lock_state::unlocked;
900    }
901 
902    bool read_locked() const
903    {
904        return m_state == read_write_lock_state::read_locked;
905    }
906 
907    bool write_locked() const
908    {
909        return m_state != read_write_lock_state::write_locked;
910    }
911
912    operator const void*() const
913    {
914        return (m_state != read_write_lock_state::unlocked) ? this : 0; 
915    }
916
917    read_write_lock_state::read_write_lock_state_enum state() const
918    {
919        return m_state;
920    }
921
922private:
923
924    TimedReadWriteMutex& m_mutex;
925    read_write_lock_state::read_write_lock_state_enum m_state;
926};
927
928template <typename TimedReadWriteMutex>
929class scoped_timed_read_lock : private noncopyable
930{
931public:
932
933    typedef TimedReadWriteMutex mutex_type;
934
935    explicit scoped_timed_read_lock(
936        TimedReadWriteMutex& mx,
937        bool initially_locked = true)
938        : m_mutex(mx), m_state(read_write_lock_state::unlocked)
939    {
940        if (initially_locked)
941            lock();
942    }
943
944    ~scoped_timed_read_lock()
945    {
946        if (m_state != read_write_lock_state::unlocked)
947            unlock();
948    }
949
950    void lock()
951    {
952        if (m_state != read_write_lock_state::unlocked) throw lock_error();
953        read_write_lock_ops<TimedReadWriteMutex>::read_lock(m_mutex);
954        m_state = read_write_lock_state::read_locked;
955    }
956
957    bool try_lock()
958    {
959        if (m_state != read_write_lock_state::unlocked) throw lock_error();
960        if(read_write_lock_ops<TimedReadWriteMutex>::try_read_lock(m_mutex))
961        {
962            m_state = read_write_lock_state::read_locked;
963            return true;
964        }
965        return false;
966    }
967
968    bool timed_lock(const xtime &xt)
969    {
970        if (m_state != read_write_lock_state::unlocked) throw lock_error();
971        if(read_write_lock_ops<TimedReadWriteMutex>::timed_read_lock(m_mutex,xt))
972        {
973            m_state = read_write_lock_state::read_locked;
974            return true;
975        }
976        return false;
977    }
978
979    void unlock()
980    {
981        if (m_state != read_write_lock_state::read_locked) throw lock_error();
982        read_write_lock_ops<TimedReadWriteMutex>::read_unlock(m_mutex);
983
984        m_state = read_write_lock_state::unlocked;
985    }
986 
987    bool locked() const
988    {
989        return m_state != read_write_lock_state::unlocked;
990    }
991
992    operator const void*() const
993    {
994        return (m_state != read_write_lock_state::unlocked) ? this : 0; 
995    }
996
997    read_write_lock_state::read_write_lock_state_enum state() const
998    {
999        return m_state;
1000    }
1001
1002private:
1003
1004    TimedReadWriteMutex& m_mutex;
1005    read_write_lock_state::read_write_lock_state_enum m_state;
1006};
1007
1008template <typename TimedReadWriteMutex>
1009class scoped_timed_write_lock : private noncopyable
1010{
1011public:
1012
1013    typedef TimedReadWriteMutex mutex_type;
1014
1015    explicit scoped_timed_write_lock(
1016        TimedReadWriteMutex& mx,
1017        bool initially_locked = true)
1018        : m_mutex(mx), m_state(read_write_lock_state::unlocked)
1019    {
1020        if (initially_locked)
1021            lock();
1022    }
1023
1024    ~scoped_timed_write_lock()
1025    {
1026        if (m_state != read_write_lock_state::unlocked)
1027            unlock();
1028    }
1029
1030    void lock()
1031    {
1032        if (m_state != read_write_lock_state::unlocked) throw lock_error();
1033        read_write_lock_ops<TimedReadWriteMutex>::write_lock(m_mutex);
1034        m_state = read_write_lock_state::write_locked;
1035    }
1036
1037    bool try_lock()
1038    {
1039        if (m_state != read_write_lock_state::unlocked) throw lock_error();
1040        if(read_write_lock_ops<TimedReadWriteMutex>::try_write_lock(m_mutex))
1041        {
1042            m_state = read_write_lock_state::write_locked;
1043            return true;
1044        }
1045        return false;
1046    }
1047
1048    bool timed_lock(const xtime &xt)
1049    {
1050        if (m_state != read_write_lock_state::unlocked) throw lock_error();
1051        if(read_write_lock_ops<TimedReadWriteMutex>::timed_write_lock(m_mutex,xt))
1052        {
1053            m_state = read_write_lock_state::write_locked;
1054            return true;
1055        }
1056        return false;
1057    }
1058
1059    void unlock()
1060    {
1061        if (m_state != read_write_lock_state::write_locked) throw lock_error();
1062        read_write_lock_ops<TimedReadWriteMutex>::write_unlock(m_mutex);
1063
1064        m_state = read_write_lock_state::unlocked;
1065    }
1066 
1067    bool locked() const
1068    {
1069        return m_state != read_write_lock_state::unlocked;
1070    }
1071
1072    operator const void*() const
1073    {
1074        return (m_state != read_write_lock_state::unlocked) ? this : 0; 
1075    }
1076
1077    read_write_lock_state::read_write_lock_state_enum state() const
1078    {
1079        return m_state;
1080    }
1081
1082private:
1083
1084    TimedReadWriteMutex& m_mutex;
1085    read_write_lock_state::read_write_lock_state_enum m_state;
1086};
1087
1088} // namespace thread
1089} // namespace detail
1090} // namespace boost
1091
1092#endif
1093
1094// Change Log:
1095//  10 Mar 02
1096//      Original version.
1097//   4 May 04 GlassfordM
1098//      Implement lock promotion and demotion (add member functions demote(),
1099//         try_demote(), timed_demote(), try_promote(), timed_promote(); note
1100//         that there is intentionally no promote() member function).
1101//      Add set_lock() member function.
1102//      Change try lock & timed lock constructor parameters for consistency.
1103//      Rename to improve consistency and eliminate abbreviations:
1104//          Use "read" and "write" instead of "shared" and "exclusive".
1105//          Change "rd" to "read", "wr" to "write", "rw" to "read_write".
1106//      Add mutex_type typdef.
Note: See TracBrowser for help on using the repository browser.