#1187 Thank You to Taras for the patch.

v0.27.3
Robin Mills 9 years ago
parent 41f14f2b7b
commit b15a401569

@ -39,6 +39,7 @@
#include "metadatum.hpp"
#include "tags.hpp"
#include "datasets.hpp"
#include "rwlock.hpp"
// + standard includes
#include <string>
@ -108,6 +109,11 @@ namespace Exiv2 {
//! Prevent assignment: not implemented.
XmpProperties& operator=(const XmpProperties& rhs);
private:
static const XmpNsInfo* nsInfoUnsafe(const std::string& prefix);
static void unregisterNsUnsafe(const std::string& ns);
static const XmpNsInfo* lookupNsRegistryUnsafe(const XmpNsInfo::Prefix& prefix);
public:
/*!
@brief Return the title (label) of the property.
@ -174,6 +180,7 @@ namespace Exiv2 {
@throw Error if no namespace is registered with \em prefix.
*/
static const XmpNsInfo* nsInfo(const std::string& prefix);
/*!
@brief Return the (preferred) prefix for schema namespace \em ns.
@param ns Schema namespace
@ -206,6 +213,8 @@ namespace Exiv2 {
@note This invalidates XMP keys generated in this namespace.
*/
static void unregisterNs(const std::string& ns);
static Internal::RWLock rwLock_;
/*!
@brief Unregister all custom namespaces.

@ -0,0 +1,138 @@
#ifndef RW_LOCK_HPP
#define RW_LOCK_HPP
#ifdef _WIN32
#include <windows.h>
#else
#include <pthread.h>
#endif
namespace Exiv2 {
namespace Internal {
#ifdef _WIN32
class RWLock
{
public:
RWLock()
{
InitializeSRWLock(&rwlock_);
}
~RWLock()
{
// do not explicitly destroy
}
void wrlock()
{
AcquireSRWLockExclusive(&rwlock_);
}
bool trywrlock()
{
return TryAcquireSRWLockExclusive(&rwlock_);
}
void rdlock()
{
AcquireSRWLockShared(&rwlock_);
}
bool tryrdlock()
{
return TryAcquireSRWLockShared(&rwlock_);
}
void rdunlock()
{
ReleaseSRWLockShared(&rwlock_);
}
void wrunlock()
{
ReleaseSRWLockExclusive(&rwlock_);
}
private:
SRWLOCK rwlock_;
};
#else
class RWLock
{
public:
RWLock(const pthread_rwlockattr_t *attr = 0)
{
pthread_rwlock_init(&rwlock_, attr);
}
~RWLock()
{
pthread_rwlock_destroy(&rwlock_);
}
int wrlock()
{
return pthread_rwlock_wrlock(&rwlock_);
}
int trywrlock()
{
return pthread_rwlock_trywrlock(&rwlock_);
}
int rdlock()
{
return pthread_rwlock_rdlock(&rwlock_);
}
int tryrdlock()
{
return pthread_rwlock_tryrdlock(&rwlock_);
}
int unlock()
{
return pthread_rwlock_unlock(&rwlock_);
}
void rdunlock() { unlock(); }
void wrunlock() { unlock(); }
private:
pthread_rwlock_t rwlock_;
};
#endif
class ScopedReadLock
{
public:
ScopedReadLock(RWLock &rwlock):
rwlock_(rwlock)
{
rwlock_.rdlock();
}
~ScopedReadLock() { rwlock_.rdunlock(); }
private:
RWLock &rwlock_;
};
class ScopedWriteLock
{
public:
ScopedWriteLock(RWLock &rwlock):
rwlock_(rwlock)
{
rwlock_.wrlock();
}
~ScopedWriteLock() { rwlock_.wrunlock(); }
private:
RWLock &rwlock_;
};
}
}
#endif // RW_LOCK_HPP

@ -51,6 +51,7 @@ EXIV2_RCSID("@(#) $Id: epsimage.cpp $")
namespace {
using namespace Exiv2;
using Exiv2::byte;
// signature of DOS EPS
const std::string dosEpsSignature = "\xC5\xD0\xD3\xC6";

@ -47,6 +47,7 @@ EXIV2_RCSID("@(#) $Id$")
namespace {
using namespace Exiv2;
using Exiv2::byte;
/*!
@brief Compare two preview images by number of pixels, if width and height

@ -39,6 +39,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "metadatum.hpp"
#include "i18n.h" // NLS support.
#include "xmp.hpp"
#include "rwlock.hpp"
#include <iostream>
#include <iomanip>
@ -2238,8 +2239,15 @@ namespace Exiv2 {
}
XmpProperties::NsRegistry XmpProperties::nsRegistry_;
Internal::RWLock XmpProperties::rwLock_;
const XmpNsInfo* XmpProperties::lookupNsRegistry(const XmpNsInfo::Prefix& prefix)
{
Internal::ScopedReadLock srl(rwLock_);
return lookupNsRegistryUnsafe(prefix);
}
const XmpNsInfo* XmpProperties::lookupNsRegistryUnsafe(const XmpNsInfo::Prefix& prefix)
{
for (NsRegistry::const_iterator i = nsRegistry_.begin();
i != nsRegistry_.end(); ++i) {
@ -2251,11 +2259,13 @@ namespace Exiv2 {
void XmpProperties::registerNs(const std::string& ns,
const std::string& prefix)
{
Internal::ScopedWriteLock swl(rwLock_);
std::string ns2 = ns;
if ( ns2.substr(ns2.size() - 1, 1) != "/"
&& ns2.substr(ns2.size() - 1, 1) != "#") ns2 += "/";
// Check if there is already a registered namespace with this prefix
const XmpNsInfo* xnp = lookupNsRegistry(XmpNsInfo::Prefix(prefix));
const XmpNsInfo* xnp = lookupNsRegistryUnsafe(XmpNsInfo::Prefix(prefix));
if (xnp) {
#ifndef SUPPRESS_WARNINGS
if (strcmp(xnp->ns_, ns2.c_str()) != 0) {
@ -2263,7 +2273,7 @@ namespace Exiv2 {
<< xnp->ns_ << " to " << ns2 << "\n";
}
#endif
unregisterNs(xnp->ns_);
unregisterNsUnsafe(xnp->ns_);
}
// Allocated memory is freed when the namespace is unregistered.
// Using malloc/free for better system compatibility in case
@ -2281,6 +2291,12 @@ namespace Exiv2 {
}
void XmpProperties::unregisterNs(const std::string& ns)
{
Internal::ScopedWriteLock swl(rwLock_);
unregisterNsUnsafe(ns);
}
void XmpProperties::unregisterNsUnsafe(const std::string& ns)
{
NsRegistry::iterator i = nsRegistry_.find(ns);
if (i != nsRegistry_.end()) {
@ -2292,15 +2308,18 @@ namespace Exiv2 {
void XmpProperties::unregisterNs()
{
Internal::ScopedWriteLock swl(rwLock_);
NsRegistry::iterator i = nsRegistry_.begin();
while (i != nsRegistry_.end()) {
NsRegistry::iterator kill = i++;
unregisterNs(kill->first);
unregisterNsUnsafe(kill->first);
}
}
std::string XmpProperties::prefix(const std::string& ns)
{
Internal::ScopedReadLock srl(rwLock_);
std::string ns2 = ns;
if ( ns2.substr(ns2.size() - 1, 1) != "/"
&& ns2.substr(ns2.size() - 1, 1) != "#") ns2 += "/";
@ -2318,9 +2337,10 @@ namespace Exiv2 {
std::string XmpProperties::ns(const std::string& prefix)
{
const XmpNsInfo* xn = lookupNsRegistry(XmpNsInfo::Prefix(prefix));
Internal::ScopedReadLock srl(rwLock_);
const XmpNsInfo* xn = lookupNsRegistryUnsafe(XmpNsInfo::Prefix(prefix));
if (xn != 0) return xn->ns_;
return nsInfo(prefix)->ns_;
return nsInfoUnsafe(prefix)->ns_;
}
const char* XmpProperties::propertyTitle(const XmpKey& key)
@ -2384,8 +2404,15 @@ namespace Exiv2 {
const XmpNsInfo* XmpProperties::nsInfo(const std::string& prefix)
{
Internal::ScopedReadLock srl(rwLock_);
return nsInfoUnsafe(prefix);
}
const XmpNsInfo* XmpProperties::nsInfoUnsafe(const std::string& prefix)
{
Internal::ScopedReadLock srl(rwLock_);
const XmpNsInfo::Prefix pf(prefix);
const XmpNsInfo* xn = lookupNsRegistry(pf);
const XmpNsInfo* xn = lookupNsRegistryUnsafe(pf);
if (!xn) xn = find(xmpNsInfo, pf);
if (!xn) throw Error(35, prefix);
return xn;

Loading…
Cancel
Save