1 // Module:  Log4CPLUS
2 // File:    pointer.cxx
3 // Created: 6/2001
4 // Author:  Tad E. Smith
5 //
6 //
7 // Copyright 2001-2010 Tad E. Smith
8 //
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
12 //
13 //     http://www.apache.org/licenses/LICENSE-2.0
14 //
15 // Unless required by applicable law or agreed to in writing, software
16 // distributed under the License is distributed on an "AS IS" BASIS,
17 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 // See the License for the specific language governing permissions and
19 // limitations under the License.
20 
21 #include "dcmtk/oflog/streams.h"
22 #include "dcmtk/oflog/helpers/pointer.h"
23 #include "dcmtk/oflog/thread/threads.h"
24 #include "dcmtk/oflog/thread/impl/syncimpl.h"
25 #include "dcmtk/oflog/config/windowsh.h"
26 #include <cassert>
27 #if defined (DCMTK_LOG4CPLUS_HAVE_INTRIN_H)
28 #include <intrin.h>
29 #endif
30 
31 
32 namespace dcmtk {
33 namespace log4cplus { namespace helpers {
34 
35 
36 ///////////////////////////////////////////////////////////////////////////////
37 // log4cplus::helpers::SharedObject dtor
38 ///////////////////////////////////////////////////////////////////////////////
39 
~SharedObject()40 SharedObject::~SharedObject()
41 {
42     assert(count == 0);
43 }
44 
45 
46 
47 ///////////////////////////////////////////////////////////////////////////////
48 // log4cplus::helpers::SharedObject public methods
49 ///////////////////////////////////////////////////////////////////////////////
50 
51 void
addReference() const52 SharedObject::addReference() const
53 {
54 #if defined (DCMTK_LOG4CPLUS_SINGLE_THREADED)
55     ++count;
56 
57 #elif defined (DCMTK_LOG4CPLUS_HAVE_CXX11_ATOMICS)
58     STD_NAMESPACE atomic_fetch_add_explicit (&count, 1u,
59         STD_NAMESPACE memory_order_relaxed);
60 
61 #elif defined (DCMTK_LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH)
62     __sync_add_and_fetch (&count, 1);
63 
64 #elif defined (_WIN32) && defined (DCMTK_LOG4CPLUS_HAVE_INTRIN_H)
65     _InterlockedIncrement (&count);
66 
67 #elif defined (_WIN32)
68     InterlockedIncrement (&count);
69 
70 #else
71     thread::MutexGuard guard (access_mutex);
72     ++count;
73 
74 #endif
75 }
76 
77 
78 void
removeReference() const79 SharedObject::removeReference() const
80 {
81     assert (count > 0);
82     bool destroy;
83 
84 #if defined (DCMTK_LOG4CPLUS_SINGLE_THREADED)
85     destroy = --count == 0;
86 
87 #elif defined (DCMTK_LOG4CPLUS_HAVE_CXX11_ATOMICS)
88     destroy = STD_NAMESPACE atomic_fetch_sub_explicit (&count, 1u,
89         STD_NAMESPACE memory_order_release) == 1;
90     if (DCMTK_LOG4CPLUS_UNLIKELY (destroy))
91         STD_NAMESPACE atomic_thread_fence (STD_NAMESPACE memory_order_acquire);
92 
93 #elif defined (DCMTK_LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH)
94     destroy = __sync_sub_and_fetch (&count, 1) == 0;
95 
96 #elif defined (_WIN32) && defined (DCMTK_LOG4CPLUS_HAVE_INTRIN_H)
97     destroy = _InterlockedDecrement (&count) == 0;
98 
99 #elif defined (_WIN32)
100     destroy = InterlockedDecrement (&count) == 0;
101 
102 #else
103     {
104         thread::MutexGuard guard (access_mutex);
105         destroy = --count == 0;
106     }
107 
108 #endif
109     if (DCMTK_LOG4CPLUS_UNLIKELY (destroy))
110         delete this;
111 }
112 
113 
114 } } // namespace log4cplus { namespace helpers
115 } // end namespace dcmtk
116