#include <CoreFoundation/CFRuntime.h>
#include <new>
#include "threading.h"
+#include <os/lock.h>
+
+#if( __cplusplus <= 201103L)
+#include <stdatomic.h>
+#endif
namespace Security {
class CFClass;
-#define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \
-\
-void *operator new(size_t size) throw(std::bad_alloc) \
-{ return SecCFObject::allocate(size, CFCLASS); } \
+#define SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR) \
\
operator APIPTR() const \
{ return (APIPTR)(this->operator CFTypeRef()); } \
\
OBJTYPE *retain() \
{ SecCFObject::handle(true); return this; } \
-APIPTR handle(bool retain = true) \
-{ return (APIPTR)SecCFObject::handle(retain); } \
+APIPTR CF_RETURNS_RETAINED handle() \
+{ return (APIPTR)SecCFObject::handle(true); } \
+APIPTR handle(bool retain) \
+{ return (APIPTR)SecCFObject::handle(retain); }
+
+#define SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \
+SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR)\
+\
+void *operator new(size_t size)\
+{ return SecCFObject::allocate(size, CFCLASS); }
+
+#define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \
+SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \
\
static OBJTYPE *required(APIPTR ptr) \
{ if (OBJTYPE *p = dynamic_cast<OBJTYPE *>(SecCFObject::required(ptr, ERRCODE))) \
struct SecRuntimeBase: CFRuntimeBase
{
- bool isNew;
+ atomic_flag isOld;
};
class SecCFObject
{
private:
- void *operator new(size_t) throw(std::bad_alloc);
+ void *operator new(size_t);
// Align up to a multiple of 16 bytes
static const size_t kAlignedRuntimeSize = SECALIGNUP(sizeof(SecRuntimeBase), 4);
uint32_t mRetainCount;
- OSSpinLock mRetainSpinLock;
+ os_unfair_lock mRetainLock;
public:
// For use by SecPointer only. Returns true once the first time it's called after the object has been created.
bool isNew()
{
SecRuntimeBase *base = reinterpret_cast<SecRuntimeBase *>(reinterpret_cast<uint8_t *>(this) - kAlignedRuntimeSize);
- bool isNew = base->isNew;
- base->isNew = false;
- return isNew;
+
+ // atomic flags start clear, and like to go high.
+ return !atomic_flag_test_and_set(&(base->isOld));
}
- static SecCFObject *optional(CFTypeRef) throw();
+ static SecCFObject *optional(CFTypeRef) _NOEXCEPT;
static SecCFObject *required(CFTypeRef, OSStatus error);
- static void *allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc);
+ static void *allocate(size_t size, const CFClass &cfclass);
SecCFObject();
virtual ~SecCFObject();
uint32_t updateRetainCount(intptr_t direction, uint32_t *oldCount);
uint32_t getRetainCount() {return updateRetainCount(0, NULL);}
- static void operator delete(void *object) throw();
- operator CFTypeRef() const throw()
+ static void operator delete(void *object) _NOEXCEPT;
+ virtual operator CFTypeRef() const _NOEXCEPT
{
return reinterpret_cast<CFTypeRef>(reinterpret_cast<const uint8_t *>(this) - kAlignedRuntimeSize);
}
// This bumps up the retainCount by 1, by calling CFRetain(), iff retain is true
- CFTypeRef handle(bool retain = true) throw();
+ CFTypeRef handle(bool retain = true) _NOEXCEPT;
virtual bool equal(SecCFObject &other);
virtual CFHashCode hash();
virtual CFStringRef copyFormattingDesc(CFDictionaryRef dict);
virtual CFStringRef copyDebugDesc();
virtual void aboutToDestruct();
- virtual Mutex* getMutexForObject();
+ virtual Mutex* getMutexForObject() const;
virtual bool mayDelete();
};
T *yield() { T *result = static_cast<T *>(ptr); ptr = NULL; return result; }
// dereference operations
- T* get () const { return static_cast<T*>(ptr); } // mimic auto_ptr
+ T* get () const { return static_cast<T*>(ptr); } // mimic unique_ptr
operator T * () const { return static_cast<T*>(ptr); }
T * operator -> () const { return static_cast<T*>(ptr); }
T & operator * () const { return *static_cast<T*>(ptr); }
+
+ SecPointer& operator=(const SecPointer& other) { SecPointerBase::operator=(other); return *this; }
};
template <class T>