Skip to main content

cluFlock/
lib.rs

1#![allow(non_snake_case)]
2
3//Copyright 2021 #UlinProject Денис Котляров
4
5//Licensed under the Apache License, Version 2.0 (the "License");
6//you may not use this file except in compliance with the License.
7//You may obtain a copy of the License at
8
9//	http://www.apache.org/licenses/LICENSE-2.0
10
11//Unless required by applicable law or agreed to in writing, software
12//distributed under the License is distributed on an "AS IS" BASIS,
13//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14//See the License for the specific language governing permissions and
15// limitations under the License.
16
17
18//#Ulin Project 2021
19//
20
21/*!
22Installation and subsequent safe removal of `flock` locks for data streams.
23
24# Use
251. Exclusive LockFile
26
27```rust
28use cluFlock::ToFlock;
29use std::fs::File;
30use std::io;
31
32fn main() -> Result<(), io::Error> {
33	let file_lock = File::create("./file")?.wait_exclusive_lock()?;
34	println!("{:?}", file_lock);
35	
36	Ok( () )
37}
38```
39
402. Exclusive LockFile (FnOnce)
41
42```rust
43use std::io::Write;
44use cluFlock::ToFlock;
45use std::fs::File;
46use std::io;
47
48fn main() -> Result<(), io::Error> {
49	File::create("./file")?.wait_exclusive_lock_fn(
50		// valid exclusive lock
51		|mut file| write!(file, "Test."), // result: Ok(usize)/Err(std::io::Error)
52		
53		// invalid lock
54		|err| Err(err.into_err()) // into_err: FlockErr -> std::io::Error
55	)?;
56	
57	Ok(())
58}
59```
60
613. Exclusive LockFile (&File)
62
63```rust
64use cluFlock::ExclusiveFlock;
65use std::fs::File;
66
67fn main() -> Result<(), std::io::Error> {
68	let file = File::create("./file")?;
69	
70	{
71		let file_lock = ExclusiveFlock::wait_lock(&file)?;
72		// file_lock, type: FlockLock<&File>
73
74		println!("{:?}", file_lock);
75	} // auto unlock ExclusiveFlock
76
77	file.sync_all()?;
78
79	Ok( () )
80}
81```
82
834. Shared LockFile (&File)
84
85```rust
86use std::fs::File;
87use cluFlock::SharedFlock;
88use std::io;
89
90fn main() -> Result<(), io::Error> {
91	let file = File::create("./test_file")?;
92	
93	let shared = SharedFlock::wait_lock(&file);
94	println!("#1shared {:?}", shared);
95	let shared2 = SharedFlock::try_lock(&file);
96	println!("#2shared {:?}", shared2);
97	
98	assert_eq!(shared.is_ok(), true);
99	assert_eq!(shared2.is_ok(), true);
100	
101	// manual or automatic unlock SharedFlock_x2
102	// drop(shared);
103	// drop(shared2);
104	
105	Ok( () )
106}
107```
108
109# Support of platforms:
1101. Unix, Linux: Full support: SharedFlock (Wait, Try), ExclusiveFlock (Wait, Try), Unlock (Wait, Try).
1111. Windows: Full support: SharedFlock (Wait, Try), ExclusiveFlock (Wait, Try), Unlock (Wait, !Try). Unlock Try is not implemented and is considered additional unsafe functionality.
112
113# Features of platforms:
1141. Unix, Linux: The flock system call only works between processes, there are no locks inside the process.
1152. Windows: System calls (LockFileEx UnlockFileEx) work between processes and within the current process. If you use Shared and Exclusive locks, you can lock yourself in the same process.
116
117# License
118
119Copyright 2021 #UlinProject Denis Kotlyarov (Денис Котляров)
120
121Licensed under the Apache License, Version 2.0
122
123*/
124
125use crate::data::err::FlockError;
126use crate::data::unlock::WaitFlockUnlock;
127use crate::element::FlockElement;
128
129// os_release
130mod os_release {
131	#[cfg(unix)]
132	pub mod unix;
133	
134	#[cfg(windows)]
135	pub mod windows;
136}
137
138#[doc(hidden)]
139pub (crate) mod sys {
140	#[cfg(unix)]
141	pub use crate::os_release::unix::*;
142	
143	#[cfg(windows)]
144	pub use crate::os_release::windows::*;
145}
146
147mod data {
148	pub mod err;
149	pub mod unlock;
150	
151	mod lock;
152	pub use self::lock::*;
153}
154
155pub use self::data::*;
156mod to;
157pub use self::to::*;
158
159pub mod element;
160
161
162/// Set exclusive lock. Only one process can hold a data flow lock.
163pub trait ExclusiveFlock where Self: FlockElement + WaitFlockUnlock + Sized {
164	#[inline]
165	fn try_lock(self) -> Result<FlockLock<Self>, FlockError<Self>> {
166		ExclusiveFlock::try_lock_fn(
167			self,
168			|sself| Ok(sself), 
169			|e| Err(e)
170		)
171	}
172	
173	#[inline]
174	fn wait_lock(self) -> Result<FlockLock<Self>, FlockError<Self>> {
175		ExclusiveFlock::wait_lock_fn(
176			self,
177			|sself| Ok(sself), 
178			|e| Err(e)
179		)
180	}
181	
182	fn try_lock_fn<F: FnOnce(FlockLock<Self>) -> R, FE: FnOnce(FlockError<Self>) -> R, R>(self, next: F, errf: FE) -> R;
183	fn wait_lock_fn<F: FnOnce(FlockLock<Self>) -> R, FE: FnOnce(FlockError<Self>) -> R, R>(self, next: F, errf: FE) -> R;
184}
185
186
187/// Set common lock, common locks can be many. An exclusive lock will wait for all shared locks to complete.
188pub trait SharedFlock where Self: FlockElement + WaitFlockUnlock + Sized {
189	#[inline]
190	fn try_lock(self) -> Result<FlockLock<Self>, FlockError<Self>> {
191		SharedFlock::try_lock_fn(
192			self,
193			|sself| Ok(sself), 
194			|e| Err(e)
195		)
196	}
197	
198	#[inline]
199	fn wait_lock(self) -> Result<FlockLock<Self>, FlockError<Self>> {
200		SharedFlock::wait_lock_fn(
201			self,
202			|sself| Ok(sself), 
203			|e| Err(e)
204		)
205	}
206	
207	fn try_lock_fn<F: FnOnce(FlockLock<Self>) -> R, FE: FnOnce(FlockError<Self>) -> R, R>(self, next: F, errf: FE) -> R;
208	fn wait_lock_fn<F: FnOnce(FlockLock<Self>) -> R, FE: FnOnce(FlockError<Self>) -> R, R>(self, next: F, errf: FE) -> R;
209}
210
211