Mercurial > foo_out_sdl
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; +};
