Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules_wearable / 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/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         LogPedantic("Failed to unlink semaphore. Errno: " << error);
38         ThrowMsg(Exception::RemoveFailed,
39                  "Failed to unlink semaphore. Errno: " << error);
40     }
41 }
42
43 Semaphore::Semaphore(size_t maxLockCount)
44 {
45     LogPedantic("Allocating unnamed semaphore:");
46     LogPedantic("    Maximum lock count: " << 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         LogPedantic("Failed to create semaphore. Errno: " << 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     LogPedantic("Allocating named semaphore:");
71     LogPedantic("    File name: " << fileName);
72     LogPedantic("    Maximum lock count: " << maxLockCount);
73     LogPedantic("    File name: " << fileName);
74     LogPedantic("    Allowed create: " << allowCreate);
75     LogPedantic("    Exclusive create: " << exclusiveCreate);
76     LogPedantic("    Permissions: " << permissions);
77     LogPedantic("    Unlink on destroy: " << unlinkOnDestroy);
78
79     sem_t *semaphore;
80
81     do {
82         if (allowCreate) {
83             if (exclusiveCreate) {
84                 semaphore = sem_open(fileName.c_str(),
85                                      O_CREAT | O_EXCL,
86                                      permissions,
87                                      static_cast<unsigned>(maxLockCount));
88             } else {
89                 semaphore = sem_open(fileName.c_str(),
90                                      O_CREAT,
91                                      permissions,
92                                      static_cast<unsigned>(maxLockCount));
93             }
94         } else {
95             semaphore = sem_open(fileName.c_str(), 0);
96         }
97     } while (semaphore == SEM_FAILED && errno == EINTR);
98
99     if (semaphore == SEM_FAILED) {
100         int error = errno;
101
102         LogPedantic("Failed to create semaphore '" << fileName
103                                                    << "'. Errno: " << error);
104
105         ThrowMsg(Exception::CreateFailed,
106                  "Failed to create semaphore '" << fileName
107                                                 << "'. Errno: " << error);
108     }
109
110     m_semaphore.named.handle = semaphore;
111
112     m_semaphore.named.name = strdup(fileName.c_str()); // May be NULL
113
114     if (m_semaphore.named.name == NULL) {
115         LogPedantic("Out of memory while duplicating semaphore name");
116     }
117
118     m_semaphore.named.unlinkOnDestroy = unlinkOnDestroy;
119
120     m_type = Type_Named;
121 }
122
123 Semaphore::~Semaphore()
124 {
125     InternalDestroy();
126 }
127
128 sem_t *Semaphore::InternalGet() const
129 {
130     switch (m_type) {
131     case Type_Unnamed:
132         return &m_semaphore.unnamed.handle;
133
134     case Type_Named:
135         return m_semaphore.named.handle;
136
137     default:
138         Assert(false && "Invalid type");
139     }
140
141     return NULL;
142 }
143
144 void Semaphore::InternalDestroy()
145 {
146     switch (m_type) {
147     case Type_Unnamed:
148         if (sem_destroy(&m_semaphore.unnamed.handle) == -1) {
149             int error = errno;
150
151             LogPedantic("Failed to destroy semaphore. Errno: " << error);
152         }
153         break;
154
155     case Type_Named:
156         if (sem_close(m_semaphore.named.handle) == -1) {
157             int error = errno;
158
159             LogPedantic("Failed to close semaphore. Errno: " << error);
160         }
161
162         if (m_semaphore.named.name != NULL) {
163             // Unlink named semaphore
164             if (m_semaphore.named.unlinkOnDestroy &&
165                 sem_unlink(m_semaphore.named.name) == -1)
166             {
167                 int error = errno;
168
169                 LogPedantic("Failed to unlink semaphore. Errno: "
170                             << error);
171             }
172
173             // Free name
174             free(m_semaphore.named.name);
175         }
176         break;
177
178     default:
179         Assert(false && "Invalid type");
180     }
181 }
182
183 void Semaphore::Lock() const
184 {
185     if (TEMP_FAILURE_RETRY(sem_wait(InternalGet())) != 0) {
186         int error = errno;
187
188         LogPedantic("Failed to lock semaphore. Errno: " << error);
189
190         ThrowMsg(Exception::LockFailed,
191                  "Failed to lock semaphore. Errno: " << error);
192     }
193 }
194
195 void Semaphore::Unlock() const
196 {
197     if (sem_post(InternalGet()) != 0) {
198         int error = errno;
199
200         LogPedantic("Failed to unlock semaphore. Errno: " << error);
201
202         ThrowMsg(Exception::UnlockFailed,
203                  "Failed to unlock semaphore. Errno: " << error);
204     }
205 }
206
207 Semaphore::ScopedLock::ScopedLock(Semaphore *semaphore) :
208     m_semaphore(semaphore)
209 {
210     Assert(semaphore != NULL);
211     m_semaphore->Lock();
212 }
213
214 Semaphore::ScopedLock::~ScopedLock()
215 {
216     Try
217     {
218         m_semaphore->Unlock();
219     }
220     Catch(Semaphore::Exception::UnlockFailed)
221     {
222         LogPedantic("Failed to leave semaphore scoped lock");
223     }
224 }
225 } // namespace DPL