]> git.buserror.net Git - polintos/scott/priv.git/blob - include/c++/util/lock.h
Initial checkin from Perforce.
[polintos/scott/priv.git] / include / c++ / util / lock.h
1 #ifndef _UTIL_LOCK_H
2 #define _UTIL_LOCK_H
3
4 // There are two basic lock types: Lock and SpinLock. A thread that
5 // blocks on a Lock may sleep until it obtains the lock.  In kernel code,
6 // a thread that blocks on a SpinLock will not sleep, but will run a busy
7 // loop until the lock is freed.  In userspace code, a SpinLock behaves
8 // as an ordinary Lock.
9
10 #ifdef _KERNEL
11 #include <kern/lock.h>
12 #endif
13
14 #include <util/spinlock.h>
15
16 namespace Lock {
17         struct AutoLock {
18                 Lock &real_lock;
19         
20                 AutoLock(Lock &lock) : real_lock(lock)
21                 {
22                         real_lock.lock();
23                 }
24                 
25                 ~AutoLock()
26                 {
27                         real_lock.unlock();
28                 }
29         };
30         
31         struct DroppableAutoLock {
32                 Lock &real_lock;
33                 bool dropped;
34                 
35                 DroppableAutoLock(Lock &lock) : real_lock(lock)
36                 {
37                         real_lock.lock();
38                         dropped = false;
39                 }
40                 
41                 ~DroppableAutoLock()
42                 {
43                         if (!dropped)
44                                 real_lock.unlock();
45                 }
46                 
47                 void lock()
48                 {
49                         assert(dropped);
50                         real_lock.lock();
51                         dropped = false;
52                 }
53                 
54                 void unlock()
55                 {
56                         assert(!dropped);
57                         dropped = true;
58                         real_lock.unlock();
59                 }
60         };
61
62         struct DoubleAutoLock {
63                 Lock &real_lock1, &real_lock2;
64         
65                 DoubleAutoLock(Lock &lock1, Lock &lock2) :
66                 real_lock1(lock1), real_lock2(lock2)
67                 {
68                         if (&lock1 < &lock2) {
69                                 real_lock1.lock();
70                                 real_lock2.lock();
71                         } else {
72                                 real_lock2.lock();
73                                 real_lock1.lock();
74                         }
75                 }
76                 
77                 ~DoubleAutoLock()
78                 {
79                         real_lock1.unlock();
80                         real_lock2.unlock();
81                 }
82         };
83 }
84
85 #endif