• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "semaphore_ex.h"
16 
17 #include <pthread.h>   // pthread_mutex_lock
18 #include <sys/types.h> // pid_t
19 #include <unistd.h>    // getpid
20 #include <fcntl.h>     // O_CREAT
21 #include <semaphore.h> // sem_t
22 
23 #include <sstream>     // ostringstream
24 #include <iomanip>     // setw/setfill
25 
26 using namespace std;
27 
28 namespace OHOS {
29 
GenUniqueName()30 std::string GenUniqueName()
31 {
32     static const uint64_t magic = 0xbcdecdeffedcedcbULL;
33     static uint64_t count = 0;
34     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
35 
36     pthread_mutex_lock(&mutex);
37     count++;
38     std::ostringstream fmt;
39     static const int outWidth = 20;
40     fmt << "_unnamed_sema_" << getpid() << "_" << magic << "_"
41         << std::setw(outWidth) << std::setfill('0') << count++;
42     pthread_mutex_unlock(&mutex);
43     return fmt.str();
44 }
45 
NamedSemaphore(size_t size)46 NamedSemaphore::NamedSemaphore(size_t size)
47     :name_(GenUniqueName()), maxCount_(size), sema_(nullptr), named_(false)
48 {
49 }
50 
NamedSemaphore(const std::string & name,size_t size)51 NamedSemaphore::NamedSemaphore(const std::string& name, size_t size)
52     :name_(name), maxCount_(size), sema_(nullptr), named_(true)
53 {
54 }
55 
~NamedSemaphore()56 NamedSemaphore::~NamedSemaphore()
57 {
58     if (!named_) {
59         Unlink();
60     }
61 }
62 
Create()63 bool NamedSemaphore::Create()
64 {
65     Unlink();
66     sema_ = sem_open(name_.c_str(), O_CREAT,
67         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, maxCount_); // mode: 0666
68     return (sema_ != SEM_FAILED);
69 }
70 
Unlink()71 bool NamedSemaphore::Unlink()
72 {
73     return sem_unlink(name_.c_str()) == 0;
74 }
75 
Open()76 bool NamedSemaphore::Open()
77 {
78     sema_ = sem_open(name_.c_str(), 0);
79     return (sema_ != SEM_FAILED);
80 }
81 
Close()82 bool NamedSemaphore::Close()
83 {
84     if (sema_ == nullptr) {
85         return false;
86     }
87 
88     if (sem_close(reinterpret_cast<sem_t *>(sema_)) == 0) {
89         sema_ = nullptr;
90         return true;
91     }
92     return false;
93 }
94 
Wait()95 bool NamedSemaphore::Wait()
96 {
97     if (sema_ == nullptr) {
98         return false;
99     }
100 
101     return (sem_wait(reinterpret_cast<sem_t *>(sema_)) == 0);
102 }
103 
TimedWait(const struct timespec & ts)104 bool NamedSemaphore::TimedWait(const struct timespec& ts)
105 {
106     if (sema_ == nullptr) {
107         return false;
108     }
109 
110     return (sem_timedwait(reinterpret_cast<sem_t *>(sema_), &ts) == 0);
111 }
112 
TryWait()113 bool NamedSemaphore::TryWait()
114 {
115     if (sema_ == nullptr) {
116         return false;
117     }
118 
119     return (sem_trywait(reinterpret_cast<sem_t *>(sema_)) == 0);
120 
121 }
122 
Post()123 bool NamedSemaphore::Post()
124 {
125     if ((sema_ == nullptr) || (GetValue() >= maxCount_)) {
126         return false;
127     }
128 
129     return (sem_post(reinterpret_cast<sem_t *>(sema_)) == 0);
130 }
131 
GetValue() const132 int NamedSemaphore::GetValue() const
133 {
134     if (sema_ == nullptr) {
135         return INVALID_SEMA_VALUE;
136     }
137 
138     int val = -1;
139     if (sem_getvalue(reinterpret_cast<sem_t *>(sema_), &val) == 0) {
140         return val;
141     }
142     return INVALID_SEMA_VALUE;
143 }
144 
Wait()145 void Semaphore::Wait()
146 {
147     std::unique_lock<std::mutex> lck(mutex_);
148     if (--count_ < 0) {
149         cv_.wait(lck);
150     }
151 }
152 
Post()153 void Semaphore::Post()
154 {
155     std::unique_lock<mutex> lck(mutex_);
156     if (++count_ <= 0) {
157         cv_.notify_one();
158     }
159 }
160 
161 } // namespace OHOS
162