DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
Lock.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 using System;
18 using System.Threading;
19 
20 namespace Deveel.Data.Transactions {
21  public sealed class Lock {
22  private bool exclusiveMode;
23  private int sharedAccess;
24 
25  internal Lock(LockingQueue queue, LockingMode mode, AccessType accessType) {
26  Queue = queue;
27  AccessType = accessType;
28  Mode = mode;
29  Queue.Acquire(this);
30  }
31 
32  private LockingQueue Queue { get; set; }
33 
34  public AccessType AccessType { get; private set; }
35 
36  public LockingMode Mode { get; private set; }
37 
38  private bool WasChecked { get; set; }
39 
40  internal ILockable Lockable {
41  get { return Queue.Lockable; }
42  }
43 
44  private void StartMode() {
45  lock (this) {
46  // If currently in exclusive mode, block until not.
47 
48  while (exclusiveMode) {
49  Monitor.Wait(this);
50  }
51 
52  if (Mode == LockingMode.Exclusive) {
53  // Set this thread to exclusive mode, and wait until all shared modes
54  // have completed.
55 
56  exclusiveMode = true;
57  while (sharedAccess > 0) {
58  Monitor.Wait(this);
59  }
60  } else if (Mode == LockingMode.Shared) {
61  // Increase the threads counter that are in shared mode.
62 
63  ++sharedAccess;
64  } else {
65  throw new InvalidOperationException("Invalid mode");
66  }
67  }
68  }
69 
70  private void EndMode() {
71  lock (this) {
72  if (Mode == LockingMode.Exclusive) {
73  exclusiveMode = false;
74  Monitor.PulseAll(this);
75  } else if (Mode == LockingMode.Shared) {
76  --sharedAccess;
77  if (sharedAccess == 0 && exclusiveMode) {
78  Monitor.PulseAll(this);
79  } else if (sharedAccess < 0) {
80  sharedAccess = 0;
81  Monitor.PulseAll(this);
82  throw new Exception("Too many 'Sahred Locks Release' calls");
83  }
84  } else {
85  throw new InvalidOperationException("Invalid mode");
86  }
87  }
88  }
89 
90  internal void Acquire() {
91  StartMode();
92  }
93 
94  internal void Release() {
95  EndMode();
96  Queue.Release(this);
97 
98  // TODO: if the lock was not check, silently report the error to the system
99  }
100 
101  internal void CheckAccess(AccessType accessType) {
102  if (AccessType == AccessType.Write &&
103  accessType != AccessType.Write)
104  throw new InvalidOperationException("Access error on Lock: Tried to Write to a non Write Lock.");
105 
106  if (!WasChecked) {
107  Queue.CheckAccess(this);
108  WasChecked = true;
109  }
110  }
111  }
112 }
LockingMode
The mode applied to a lock over a resource during a transaction.
Definition: LockingMode.cs:24
Lock(LockingQueue queue, LockingMode mode, AccessType accessType)
Definition: Lock.cs:25
void CheckAccess(AccessType accessType)
Definition: Lock.cs:101