diff foosdk/sdk/foobar2000/SDK/file_lock_manager.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/foobar2000/SDK/file_lock_manager.h	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,77 @@
+#pragma once
+
+/*
+File lock management API
+Historical note: while this API was first published in a 2018 release of the SDK, it had been around for at least a decade and is supported in all fb2k versions from 0.9 up.
+The semantics are similar to those of blocking POSIX flock().
+Since read locks are expected to be held for a long period of time - for an example, when playing an audio track, a holder of such lock can query whether someone else is waiting for this lock to be released.
+Various audio file operations performed by fb2k core use file locks to synchronize access to the files - in particular, to allow graceful updates of tags on the currently playing track.
+
+Usage examples:
+If you want to write tags to an audio file, using low level methods such as input or album_art_editor APIs-
+  Obtain a write lock before accessing your file and release it when done.
+If you want to keep an audio file open for an extended period of time and allow others to write to it-
+  Obtain a read lock, check is_release_requested() on it periodically; when it returns true, close the file, release the lock, obtain a new lock (which will block you until the peding write operation has completed), reopen the file and resume decoding where you left.
+
+Final note:
+Majority of the fb2k components will never need this API. 
+If you carry out tag updates via metadb_io, the locking is already dealt with by fb2k core.
+*/
+
+//! An instance of a file lock object. Use file_lock_manager to instantiate.
+class NOVTABLE file_lock : public service_base {
+public:
+	//! Returns whether we're blocking other attempts to access this file. A read lock does not block other read locks, but a write lock requires exclusive access.\n
+	//! Typically, time consuming read operations check this periodically and close the file / release the lock / reacquire the lock / reopen the file when signaled.
+	virtual bool is_release_requested() = 0;
+
+	FB2K_MAKE_SERVICE_INTERFACE(file_lock, service_base);
+};
+
+typedef service_ptr_t<file_lock> file_lock_ptr;
+
+//! \since 1.5
+//! Modern version of file locking. \n
+//! A read lock can be interrupted by a write lock request, from the thread that requested writing. \n
+class NOVTABLE file_lock_interrupt : public service_base {
+    FB2K_MAKE_SERVICE_INTERFACE(file_lock_interrupt, service_base);
+public:
+    //! Please note that interrupt() is called outside any sync scopes and may be called after lock reference has been released. \n
+    //! It is implementer's responsibility to safeguard against such. \n
+    //! The interrupt() function must *never* fail, unless aborted by calling context - which means that whoever asked for write access is aborting whatever they're doing. \n
+    //! This function may block for as long as it takes to release the owned resources, but must be able to abort cleanly if doing so. \n
+    //! If the function was aborted, it may be called again on the same object. \n
+    //! If the function succeeded, it will not be called again on the same object; the object will be released immediately after.
+    virtual void interrupt( abort_callback & aborter ) = 0;
+    
+    static file_lock_interrupt::ptr create( std::function< void (abort_callback&)> );
+};
+
+//! Entry point class for obtaining file_lock objects.
+class NOVTABLE file_lock_manager : public service_base {
+public:
+	enum t_mode {
+		mode_read = 0,
+		mode_write
+	};
+	//! Acquires a read or write lock for this file path. \n
+	//! If asked for read access, waits until nobody else holds a write lock for this path (but others may read at the same time).
+	//! If asked for write access, access until nobody else holds a read or write lock for this path. \n
+	//! The semantics are similar to those of blocking POSIX flock().
+	virtual file_lock_ptr acquire(const char * p_path, t_mode p_mode, abort_callback & p_abort) = 0;
+
+	//! Helper, calls acquire() with mode_read.
+	file_lock_ptr acquire_read(const char * p_path, abort_callback & p_abort) { return acquire(p_path, mode_read, p_abort); }
+	//! Helper, calls acquire() with mode_write.
+	file_lock_ptr acquire_write(const char * p_path, abort_callback & p_abort) { return acquire(p_path, mode_write, p_abort); }
+
+
+	FB2K_MAKE_SERVICE_COREAPI(file_lock_manager);
+};
+
+// \since 1.5
+class NOVTABLE file_lock_manager_v2 : public file_lock_manager {
+	FB2K_MAKE_SERVICE_COREAPI_EXTENSION( file_lock_manager_v2, file_lock_manager );
+public:
+	virtual fb2k::objRef acquire_read_v2(const char * p_path, file_lock_interrupt::ptr interruptHandler, abort_callback & p_abort) = 0;
+};