Update User Agent String
[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 <dpl/semaphore.h>
23 #include <dpl/assert.h>
24 #include <dpl/log/log.h>
25 #include <errno.h>
26 #include <malloc.h>
27 #include <cstring>
28 #include <fcntl.h>
29 #include <unistd.h>
30
31 namespace DPL
32 {
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     {
83         if (allowCreate)
84         {
85             if (exclusiveCreate)
86             {
87                 semaphore = sem_open(fileName.c_str(),
88                                      O_CREAT | O_EXCL,
89                                      permissions,
90                                      static_cast<unsigned>(maxLockCount));
91             }
92             else
93             {
94                 semaphore = sem_open(fileName.c_str(),
95                                      O_CREAT,
96                                      permissions,
97                                      static_cast<unsigned>(maxLockCount));
98             }
99         }
100         else
101         {
102             semaphore = sem_open(fileName.c_str(), 0);
103         }
104     }
105     while (semaphore == SEM_FAILED && errno == EINTR);
106
107     if (semaphore == SEM_FAILED)
108     {
109         int error = errno;
110
111         LogPedantic("Failed to create semaphore '" << fileName
112                     << "'. Errno: " << error);
113
114         ThrowMsg(Exception::CreateFailed,
115                  "Failed to create semaphore '" << fileName
116                      << "'. Errno: " << error);
117     }
118
119     m_semaphore.named.handle = semaphore;
120
121     m_semaphore.named.name = strdup(fileName.c_str()); // May be NULL
122
123     if (m_semaphore.named.name == NULL)
124         LogPedantic("Out of memory while duplicating semaphore name");
125
126     m_semaphore.named.unlinkOnDestroy = unlinkOnDestroy;
127
128     m_type = Type_Named;
129 }
130
131 Semaphore::~Semaphore()
132 {
133     InternalDestroy();
134 }
135
136 sem_t *Semaphore::InternalGet() const
137 {
138     switch (m_type)
139     {
140         case Type_Unnamed:
141             return &m_semaphore.unnamed.handle;
142
143         case Type_Named:
144             return m_semaphore.named.handle;
145
146         default:
147             Assert(false && "Invalid type");
148     }
149
150     return NULL;
151 }
152
153 void Semaphore::InternalDestroy()
154 {
155     switch (m_type)
156     {
157         case Type_Unnamed:
158             if (sem_destroy(&m_semaphore.unnamed.handle) == -1)
159             {
160                 int error = errno;
161
162                 LogPedantic("Failed to destroy semaphore. Errno: " << error);
163             }
164             break;
165
166         case Type_Named:
167             if (sem_close(m_semaphore.named.handle) == -1)
168             {
169                 int error = errno;
170
171                 LogPedantic("Failed to close semaphore. Errno: " << error);
172             }
173
174             if (m_semaphore.named.name != NULL)
175             {
176                 // Unlink named semaphore
177                 if (m_semaphore.named.unlinkOnDestroy &&
178                     sem_unlink(m_semaphore.named.name) == -1)
179                 {
180                     int error = errno;
181
182                     LogPedantic("Failed to unlink semaphore. Errno: "
183                                 << error);
184                 }
185
186                 // Free name
187                 free(m_semaphore.named.name);
188             }
189             break;
190
191         default:
192             Assert(false && "Invalid type");
193     }
194 }
195
196 void Semaphore::Lock() const
197 {
198     if (TEMP_FAILURE_RETRY(sem_wait(InternalGet())) != 0)
199     {
200         int error = errno;
201
202         LogPedantic("Failed to lock semaphore. Errno: " << error);
203
204         ThrowMsg(Exception::LockFailed,
205             "Failed to lock semaphore. Errno: " << error);
206     }
207 }
208
209 void Semaphore::Unlock() const
210 {
211     if (sem_post(InternalGet()) != 0)
212     {
213         int error = errno;
214
215         LogPedantic("Failed to unlock semaphore. Errno: " << error);
216
217         ThrowMsg(Exception::UnlockFailed,
218             "Failed to unlock semaphore. Errno: " << error);
219     }
220 }
221
222 Semaphore::ScopedLock::ScopedLock(Semaphore *semaphore)
223     : m_semaphore(semaphore)
224 {
225     Assert(semaphore != NULL);
226     m_semaphore->Lock();
227 }
228
229 Semaphore::ScopedLock::~ScopedLock()
230 {
231     Try
232     {
233         m_semaphore->Unlock();
234     }
235     Catch (Semaphore::Exception::UnlockFailed)
236     {
237         LogPedantic("Failed to leave semaphore scoped lock");
238     }
239 }
240 } // namespace DPL