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