-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathlock_helper.py
More file actions
executable file
·120 lines (95 loc) · 2.73 KB
/
Copy pathlock_helper.py
File metadata and controls
executable file
·120 lines (95 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import os
import multiprocessing
import threading
import platform
from enum import Enum, unique
from readerwriterlock import rwlock
from pathlib import Path
if platform.system().lower() != 'windows':
import fcntl
else:
fcntl = None
@unique
class LockContextType(Enum):
"""
Enum to express the type of the lock
"""
THREAD_LOCK = 1
PROCESS_LOCK = 2
_LOCK_TYPE_MAPPING = {
LockContextType.THREAD_LOCK: threading.Lock,
LockContextType.PROCESS_LOCK: multiprocessing.Lock,
}
class LockContext(object):
"""
Overview:
Generate a LockContext in order to make sure the thread safety.
Interfaces:
``__init__``, ``__enter__``, ``__exit__``
Example:
>>> with LockContext() as lock:
>>> print("Do something here.")
"""
def __init__(self, type_: LockContextType = LockContextType.THREAD_LOCK):
r"""
Overview:
Init the lock according to given type
"""
self.lock = _LOCK_TYPE_MAPPING[type_]()
def acquire(self):
self.lock.acquire()
def release(self):
self.lock.release()
def __enter__(self):
"""
Overview:
Entering the context and acquire lock
"""
self.lock.acquire()
def __exit__(self, *args, **kwargs):
"""
Overview:
Quiting the context and release lock
"""
self.lock.release()
rw_lock_mapping = {}
def get_rw_file_lock(name: str, op: str):
r'''
Overview:
Get generated file lock with name and operator
Arguments:
- name (:obj:`str`) Lock's name.
- op (:obj:`str`) Assigned operator, i.e. ``read`` or ``write``.
Returns:
- (:obj:`RWLockFairD`) Generated rwlock
'''
assert op in ['read', 'write']
if name not in rw_lock_mapping:
rw_lock_mapping[name] = rwlock.RWLockFairD()
lock = rw_lock_mapping[name]
if op == 'read':
return lock.gen_rlock()
elif op == 'write':
return lock.gen_wlock()
class FcntlContext:
def __init__(self, lock_path: str) -> None:
self.lock_path = lock_path
self.f = None
def __enter__(self) -> None:
assert self.f is None, self.lock_path
self.f = open(self.lock_path, 'w')
fcntl.flock(self.f.fileno(), fcntl.LOCK_EX)
def __exit__(self, *args, **kwargs) -> None:
self.f.close()
self.f = None
def get_file_lock(name: str, op: str) -> None:
if fcntl is None:
return get_rw_file_lock(name, op)
else:
lock_name = name + '.lock'
if not os.path.isfile(lock_name):
try:
Path(lock_name).touch()
except Exception as e:
pass
return FcntlContext(lock_name)