Commit a950edb4 authored by Manfred Georg's avatar Manfred Georg Committed by Michael Niedermayer

avcodec/utils: av_lockmgr_register defines behavior on failure.

The register function now specifies that the user callback should
leave things in the same state that it found them on failure but
that failure to destroy is ignored by the library.  The register
function is now explicit about its behavior on failure
(it unregisters the previous callback and destroys all mutex).
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent cdd6f059
...@@ -5121,16 +5121,26 @@ enum AVLockOp { ...@@ -5121,16 +5121,26 @@ enum AVLockOp {
/** /**
* Register a user provided lock manager supporting the operations * Register a user provided lock manager supporting the operations
* specified by AVLockOp. mutex points to a (void *) where the * specified by AVLockOp. The "mutex" argument to the function points
* lockmgr should store/get a pointer to a user allocated mutex. It's * to a (void *) where the lockmgr should store/get a pointer to a user
* NULL upon AV_LOCK_CREATE and != NULL for all other ops. * allocated mutex. It is NULL upon AV_LOCK_CREATE and equal to the
* * value left by the last call for all other ops. If the lock manager is
* @param cb User defined callback. Note: FFmpeg may invoke calls to this * unable to perform the op then it should leave the mutex in the same
* callback during the call to av_lockmgr_register(). * state as when it was called and return a non-zero value. However,
* Thus, the application must be prepared to handle that. * when called with AV_LOCK_DESTROY the mutex will always be assumed to
* If cb is set to NULL the lockmgr will be unregistered. * have been successfully destroyed. If av_lockmgr_register succeeds
* Also note that during unregistration the previously registered * it will return a non-negative value, if it fails it will return a
* lockmgr callback may also be invoked. * negative value and destroy all mutex and unregister all callbacks.
* av_lockmgr_register is not thread-safe, it must be called from a
* single thread before any calls which make use of locking are used.
*
* @param cb User defined callback. av_lockmgr_register invokes calls
* to this callback and the previously registered callback.
* The callback will be used to create more than one mutex
* each of which must be backed by its own underlying locking
* mechanism (i.e. do not use a single static object to
* implement your lock manager). If cb is set to NULL the
* lockmgr will be unregistered.
*/ */
int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)); int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op));
......
...@@ -3474,22 +3474,32 @@ AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel) ...@@ -3474,22 +3474,32 @@ AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel)
int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op))
{ {
if (lockmgr_cb) { if (lockmgr_cb) {
if (lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY)) // There is no good way to rollback a failure to destroy the
return -1; // mutex, so we ignore failures.
if (lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY)) lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY);
return -1; lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY);
lockmgr_cb = NULL;
codec_mutex = NULL; codec_mutex = NULL;
avformat_mutex = NULL; avformat_mutex = NULL;
} }
if (cb) {
void *new_codec_mutex = NULL;
void *new_avformat_mutex = NULL;
int err;
if (err = cb(&new_codec_mutex, AV_LOCK_CREATE)) {
return err > 0 ? AVERROR_EXTERNAL : err;
}
if (err = cb(&new_avformat_mutex, AV_LOCK_CREATE)) {
// Ignore failures to destroy the newly created mutex.
cb(&new_codec_mutex, AV_LOCK_DESTROY);
return err > 0 ? AVERROR_EXTERNAL : err;
}
lockmgr_cb = cb; lockmgr_cb = cb;
codec_mutex = new_codec_mutex;
if (lockmgr_cb) { avformat_mutex = new_avformat_mutex;
if (lockmgr_cb(&codec_mutex, AV_LOCK_CREATE))
return -1;
if (lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE))
return -1;
} }
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment