summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2009-07-29 14:23:36 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2009-07-29 14:23:36 +0800
commit511a99232b217b625b8ba88d1cb73698ac842b42 (patch)
treea950c7fbbff1f3095752a527af6e0f0b59c57e9d
parent7eb03463c82f7951994f1aaf005032fb19fa1da2 (diff)
Atomically increment and decrement the refcounts for Audiere objects.
-rw-r--r--src/audiere.h83
-rw-r--r--src/utility.cpp29
2 files changed, 76 insertions, 36 deletions
diff --git a/src/audiere.h b/src/audiere.h
index dca64cf..bbeee49 100644
--- a/src/audiere.h
+++ b/src/audiere.h
@@ -187,39 +187,6 @@ namespace audiere {
/**
- * A basic implementation of the RefCounted interface. Derive
- * your implementations from RefImplementation<YourInterface>.
- */
- template<class Interface>
- class RefImplementation : public Interface {
- protected:
- RefImplementation() {
- m_ref_count = 0;
- }
-
- /**
- * So the implementation can put its destruction logic in the destructor,
- * as natural C++ code does.
- */
- virtual ~RefImplementation() { }
-
- public:
- void ADR_CALL ref() {
- ++m_ref_count;
- }
-
- void ADR_CALL unref() {
- if (--m_ref_count == 0) {
- delete this;
- }
- }
-
- private:
- int m_ref_count;
- };
-
-
- /**
* Represents a random-access file, usually stored on a disk. Files
* are always binary: that is, they do no end-of-line
* transformations. File objects are roughly analogous to ANSI C
@@ -1047,6 +1014,9 @@ namespace audiere {
ADR_FUNCTION(const char*) AdrGetVersion();
+ ADR_FUNCTION(long) AdrAtomicIncrement(volatile long& var);
+ ADR_FUNCTION(long) AdrAtomicDecrement(volatile long& var);
+
/**
* Returns a formatted string that lists the file formats that Audiere
* supports. This function is DLL-safe.
@@ -1139,6 +1109,20 @@ namespace audiere {
}
+ /**
+ * Atomically increments a counter. Returns incremented value.
+ */
+ inline long AtomicIncrement(volatile long& var) {
+ return hidden::AdrAtomicIncrement(var);
+ }
+
+ /**
+ * Atomically decrements a counter. Returns decremented value.
+ */
+ inline long AtomicDecrement(volatile long& var) {
+ return hidden::AdrAtomicDecrement(var);
+ }
+
inline void SplitString(
std::vector<std::string>& out,
const char* in,
@@ -1560,6 +1544,39 @@ namespace audiere {
return hidden::AdrOpenMIDIDevice(device);
}
+
+ /**
+ * A basic implementation of the RefCounted interface. Derive
+ * your implementations from RefImplementation<YourInterface>.
+ */
+ template<class Interface>
+ class RefImplementation : public Interface {
+ protected:
+ RefImplementation() {
+ m_ref_count = 0;
+ }
+
+ /**
+ * So the implementation can put its destruction logic in the destructor,
+ * as natural C++ code does.
+ */
+ virtual ~RefImplementation() { }
+
+ public:
+ void ADR_CALL ref() {
+ AtomicIncrement(m_ref_count);
+ }
+
+ void ADR_CALL unref() {
+ if (AtomicDecrement(m_ref_count) == 0) {
+ delete this;
+ }
+ }
+
+ private:
+ volatile long m_ref_count;
+ };
+
}
diff --git a/src/utility.cpp b/src/utility.cpp
index fd220d6..1a5e295 100644
--- a/src/utility.cpp
+++ b/src/utility.cpp
@@ -2,11 +2,11 @@
#pragma warning(disable : 4786)
#endif
+#ifdef WIN32
+#include <windows.h>
+#endif
#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-
#include "utility.h"
#include "internal.h"
@@ -89,6 +89,29 @@ namespace audiere {
}
+#ifdef WIN32
+
+ ADR_EXPORT(long) AdrAtomicIncrement(volatile long& var) {
+ return InterlockedIncrement(&var);
+
+ }
+
+ ADR_EXPORT(long) AdrAtomicDecrement(volatile long& var) {
+ return InterlockedDecrement(&var);
+ }
+
+#else
+
+ ADR_EXPORT(long) AdrAtomicIncrement(volatile long& var) {
+ return ++var;
+ }
+
+ ADR_EXPORT(long) AdrAtomicDecrement(volatile long& var) {
+ return --var;
+ }
+
+#endif
+
ADR_EXPORT(int) AdrGetSampleSize(SampleFormat format) {
switch (format) {
case SF_U8: return 1;