Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules / core / src / semaphore.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        semaphore.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of semaphore
21  */
22 #include <stddef.h>
23 #include <dpl/semaphore.h>
24 #include <dpl/assert.h>
25 #include <dpl/log/wrt_log.h>
26 #include <errno.h>
27 #include <malloc.h>
28 #include <cstring>
29 #include <fcntl.h>
30 #include <unistd.h>
31
32 namespace DPL {
33 void Semaphore::Remove(const std::string &fileName)
34 {
35     if (sem_unlink(fileName.c_str()) == -1) {
36         int error = errno;
37         WrtLogD("Failed to unlink semaphore. Errno: %i", error);
38         ThrowMsg(Exception::RemoveFailed,
39                  "Failed to unlink semaphore. Errno: " << error);
40     }
41 }
42
43 Semaphore::Semaphore(size_t maxLockCount)
44 {
45     WrtLogD("Allocating unnamed semaphore:");
46     WrtLogD("    Maximum lock count: %u", maxLockCount);
47
48     if (-1 == sem_init(&m_semaphore.unnamed.handle,
49                        0,
50                        static_cast<unsigned>(maxLockCount)))
51     {
52         int error = errno;
53
54         WrtLogD("Failed to create semaphore. Errno: %i", error);
55
56         ThrowMsg(Exception::CreateFailed,
57                  "Failed to create semaphore. Errno: " << error);
58     }
59
60     m_type = Type_Unnamed;
61 }
62
63 Semaphore::Semaphore(const std::string &fileName,
64                      bool allowCreate,
65                      bool exclusiveCreate,
66                      size_t maxLockCount,
67                      int permissions,
68                      bool unlinkOnDestroy)
69 {
70     WrtLogD("Allocating named semaphore:");
71     WrtLogD("    File name: %s", fileName.c_str());
72     WrtLogD("    Maximum lock count: %u", maxLockCount);
73     WrtLogD("    Allowed create: %s", allowCreate ? "true" : "false");
74     WrtLogD("    Exclusive create: %s", exclusiveCreate ? "true" : "false");
75     WrtLogD("    Permissions: %i", permissions);
76     WrtLogD("    Unlink on destroy: %s", unlinkOnDestroy ? "true" : "false");
77
78     sem_t *semaphore;
79
80     do {
81         if (allowCreate) {
82             if (exclusiveCreate) {
83                 semaphore = sem_open(fileName.c_str(),
84                                      O_CREAT | O_EXCL,
85                                      permissions,
86                                      static_cast<unsigned>(maxLockCount));
87             } else {
88                 semaphore = sem_open(fileName.c_str(),
89                                      O_CREAT,
90                                      permissions,
91                                      static_cast<unsigned>(maxLockCount));
92             }
93         } else {
94             semaphore = sem_open(fileName.c_str(), 0);
95         }
96     } while (semaphore == SEM_FAILED && errno == EINTR);
97
98     if (semaphore == SEM_FAILED) {
99         int error = errno;
100
101         WrtLogD("Failed to create semaphore '%s'. Errno: %i", fileName.c_str(), error);
102
103         ThrowMsg(Exception::CreateFailed,
104                  "Failed to create semaphore '" << fileName
105                                                 << "'. Errno: " << error);
106     }
107
108     m_semaphore.named.handle = semaphore;
109
110     m_semaphore.named.name = strdup(fileName.c_str()); // May be NULL
111
112     if (m_semaphore.named.name == NULL) {
113         WrtLogD("Out of memory while duplicating semaphore name");
114     }
115
116     m_semaphore.named.unlinkOnDestroy = unlinkOnDestroy;
117
118     m_type = Type_Named;
119 }
120
121 Semaphore::~Semaphore()
122 {
123     InternalDestroy();
124 }
125
126 sem_t *Semaphore::InternalGet() const
127 {
128     switch (m_type) {
129     case Type_Unnamed:
130         return &m_semaphore.unnamed.handle;
131
132     case Type_Named:
133         return m_semaphore.named.handle;
134
135     default:
136         Assert(false && "Invalid type");
137     }
138
139     return NULL;
140 }
141
142 void Semaphore::InternalDestroy()
143 {
144     switch (m_type) {
145     case Type_Unnamed:
146         if (sem_destroy(&m_semaphore.unnamed.handle) == -1) {
147             int error = errno;
148
149             WrtLogD("Failed to destroy semaphore. Errno: %i", error);
150         }
151         break;
152
153     case Type_Named:
154         if (sem_close(m_semaphore.named.handle) == -1) {
155             int error = errno;
156
157             WrtLogD("Failed to close semaphore. Errno: %i", error);
158         }
159
160         if (m_semaphore.named.name != NULL) {
161             // Unlink named semaphore
162             if (m_semaphore.named.unlinkOnDestroy &&
163                 sem_unlink(m_semaphore.named.name) == -1)
164             {
165                 int error = errno;
166
167                 WrtLogD("Failed to unlink semaphore. Errno: %i", error);
168             }
169
170             // Free name
171             free(m_semaphore.named.name);
172         }
173         break;
174
175     default:
176         Assert(false && "Invalid type");
177     }
178 }
179
180 void Semaphore::Lock() const
181 {
182     if (TEMP_FAILURE_RETRY(sem_wait(InternalGet())) != 0) {
183         int error = errno;
184
185         WrtLogD("Failed to lock semaphore. Errno: %i", error);
186
187         ThrowMsg(Exception::LockFailed,
188                  "Failed to lock semaphore. Errno: " << error);
189     }
190 }
191
192 void Semaphore::Unlock() const
193 {
194     if (sem_post(InternalGet()) != 0) {
195         int error = errno;
196
197         WrtLogD("Failed to unlock semaphore. Errno: %i", error);
198
199         ThrowMsg(Exception::UnlockFailed,
200                  "Failed to unlock semaphore. Errno: " << error);
201     }
202 }
203
204 Semaphore::ScopedLock::ScopedLock(Semaphore *semaphore) :
205     m_semaphore(semaphore)
206 {
207     Assert(semaphore != NULL);
208     m_semaphore->Lock();
209 }
210
211 Semaphore::ScopedLock::~ScopedLock()
212 {
213     Try
214     {
215         m_semaphore->Unlock();
216     }
217     Catch(Semaphore::Exception::UnlockFailed)
218     {
219         WrtLogD("Failed to leave semaphore scoped lock");
220     }
221 }
222 } // namespace DPL