Skip to content

Commit 4795841

Browse files
committed
[SourceKit] Add Semaphore to SourceKitSupport's concurrency module
Includes a libdispatch-based implementation.
1 parent 2e9f13e commit 4795841

File tree

6 files changed

+89
-49
lines changed

6 files changed

+89
-49
lines changed

tools/SourceKit/include/SourceKit/Support/Concurrency.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,55 @@
1717

1818
namespace SourceKit {
1919

20+
class Semaphore {
21+
public:
22+
Semaphore(long count) {
23+
ImplObj = Impl::create(count);
24+
}
25+
~Semaphore() {
26+
if (ImplObj)
27+
Impl::release(ImplObj);
28+
}
29+
30+
void signal() {
31+
Impl::signal(ImplObj);
32+
}
33+
34+
bool wait() {
35+
return Impl::wait(ImplObj);
36+
}
37+
38+
bool wait(long milliseconds) {
39+
return Impl::wait(ImplObj, milliseconds);
40+
}
41+
42+
Semaphore(const Semaphore &Other) = delete;
43+
Semaphore(Semaphore &&Other) {
44+
ImplObj = std::move(Other.ImplObj);
45+
Other.ImplObj = Impl::Ty();
46+
}
47+
48+
Semaphore &operator=(const Semaphore &Other) = delete;
49+
Semaphore &operator=(Semaphore &&Other) {
50+
Semaphore Tmp(std::move(Other));
51+
std::swap(ImplObj, Tmp.ImplObj);
52+
return *this;
53+
}
54+
private:
55+
// Platform-specific implementation.
56+
struct Impl {
57+
typedef void *Ty;
58+
static Ty create(long count);
59+
static void signal(Ty Obj);
60+
static bool wait(Ty Obj);
61+
static bool wait(Ty Obj, long milliseconds);
62+
static void retain(Ty Obj);
63+
static void release(Ty Obj);
64+
};
65+
66+
Impl::Ty ImplObj;
67+
};
68+
2069
class WorkQueue {
2170
public:
2271
enum class Dequeuing {

tools/SourceKit/lib/Support/Concurrency-Mac.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,34 @@
2121

2222
using namespace SourceKit;
2323

24+
void *Semaphore::Impl::create(long count) {
25+
return dispatch_semaphore_create(count);
26+
}
27+
28+
void Semaphore::Impl::signal(Ty Obj) {
29+
dispatch_semaphore_signal(dispatch_semaphore_t(Obj));
30+
}
31+
32+
bool Semaphore::Impl::wait(Ty Obj) {
33+
return dispatch_semaphore_wait(dispatch_semaphore_t(Obj),
34+
DISPATCH_TIME_FOREVER);
35+
}
36+
37+
bool Semaphore::Impl::wait(Ty Obj, long milliseconds) {
38+
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW,
39+
milliseconds * NSEC_PER_MSEC);
40+
return dispatch_semaphore_wait(dispatch_semaphore_t(Obj), timeout);
41+
}
42+
43+
void Semaphore::Impl::retain(Ty Obj) {
44+
dispatch_retain(dispatch_semaphore_t(Obj));
45+
}
46+
47+
void Semaphore::Impl::release(Ty Obj) {
48+
dispatch_release(dispatch_semaphore_t(Obj));
49+
}
50+
51+
2452
static dispatch_queue_priority_t toDispatchPriority(WorkQueue::Priority Prio) {
2553
switch (Prio) {
2654
case WorkQueue::Priority::High: return DISPATCH_QUEUE_PRIORITY_HIGH;

tools/SourceKit/tools/sourcekitd-test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ endif()
1111
add_sourcekit_executable(sourcekitd-test
1212
sourcekitd-test.cpp
1313
TestOptions.cpp
14-
DEPENDS ${SOURCEKITD_TEST_DEPEND}
14+
DEPENDS ${SOURCEKITD_TEST_DEPEND} SourceKitSupport
1515
clangRewrite clangLex clangBasic
1616
COMPONENT_DEPENDS support option
1717
)

tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "sourcekitd/sourcekitd.h"
1414

1515
#include "TestOptions.h"
16+
#include "SourceKit/Support/Concurrency.h"
1617
#include "clang/Rewrite/Core/RewriteBuffer.h"
1718
#include "llvm/ADT/ArrayRef.h"
1819
#include "llvm/ADT/Optional.h"
@@ -149,7 +150,7 @@ static sourcekitd_uid_t SemaDiagnosticStage;
149150

150151
static sourcekitd_uid_t NoteDocUpdate;
151152

152-
static dispatch_semaphore_t semaSemaphore;
153+
static SourceKit::Semaphore semaSemaphore(0);
153154
static sourcekitd_response_t semaResponse;
154155
static const char *semaName;
155156

@@ -222,8 +223,6 @@ static int skt_main(int argc, const char **argv) {
222223

223224
NoteDocUpdate = sourcekitd_uid_get_from_cstr("source.notification.editor.documentupdate");
224225

225-
semaSemaphore = dispatch_semaphore_create(0);
226-
227226
RequestProtocolVersion = sourcekitd_uid_get_from_cstr("source.request.protocol_version");
228227
RequestDemangle = sourcekitd_uid_get_from_cstr("source.request.demangle");
229228
RequestMangleSimpleClass = sourcekitd_uid_get_from_cstr("source.request.mangle_simple_class");
@@ -864,8 +863,7 @@ static void getSemanticInfo(sourcekitd_variant_t Info, StringRef Filename) {
864863

865864
// Wait for the notification that semantic info is available.
866865
// But only for 1 min.
867-
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60);
868-
bool expired = dispatch_semaphore_wait(semaSemaphore, when);
866+
bool expired = semaSemaphore.wait(60 * 1000);
869867
if (expired) {
870868
llvm::report_fatal_error("Never got notification for semantic info");
871869
}
@@ -914,7 +912,7 @@ static void notification_receiver(sourcekitd_response_t resp) {
914912
sourcekitd_request_dictionary_set_string(edReq, KeySourceText, "");
915913
semaResponse = sourcekitd_send_request_sync(edReq);
916914
sourcekitd_request_release(edReq);
917-
dispatch_semaphore_signal(semaSemaphore);
915+
semaSemaphore.signal();
918916
}
919917
}
920918

tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
// FIXME: Portability ?
2222
#include <Block.h>
23-
#include <dispatch/dispatch.h>
2423

2524
#ifdef LLVM_ON_WIN32
2625
#define WIN32_LEAN_AND_MEAN
@@ -104,16 +103,15 @@ void sourcekitd::set_interrupted_connection_handler(
104103
//===----------------------------------------------------------------------===//
105104

106105
sourcekitd_response_t sourcekitd_send_request_sync(sourcekitd_object_t req) {
107-
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
106+
Semaphore sema(0);
108107

109108
sourcekitd_response_t ReturnedResp;
110109
sourcekitd::handleRequest(req, [&](sourcekitd_response_t resp) {
111110
ReturnedResp = resp;
112-
dispatch_semaphore_signal(sema);
111+
sema.signal();
113112
});
114113

115-
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
116-
dispatch_release(sema);
114+
sema.wait();
117115
return ReturnedResp;
118116
}
119117

unittests/SourceKit/SwiftLang/CursorInfoTest.cpp

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@
1313
#include "SourceKit/Core/Context.h"
1414
#include "SourceKit/Core/LangSupport.h"
1515
#include "SourceKit/Core/NotificationCenter.h"
16+
#include "SourceKit/Support/Concurrency.h"
1617
#include "llvm/Support/MemoryBuffer.h"
1718
#include "llvm/Support/Path.h"
1819
#include "gtest/gtest.h"
1920

20-
// FIXME: Portability.
21-
#include <dispatch/dispatch.h>
22-
2321
using namespace SourceKit;
2422
using namespace llvm;
2523

@@ -98,18 +96,12 @@ struct TestCursorInfo {
9896
class CursorInfoTest : public ::testing::Test {
9997
SourceKit::Context Ctx{ getRuntimeLibPath() };
10098
std::atomic<int> NumTasks;
101-
dispatch_semaphore_t TaskSema = nullptr;
10299

103100
public:
104101
LangSupport &getLang() { return Ctx.getSwiftLangSupport(); }
105102

106103
void SetUp() {
107104
NumTasks = 0;
108-
TaskSema = dispatch_semaphore_create(0);
109-
}
110-
111-
void TearDown() {
112-
dispatch_release(TaskSema);
113105
}
114106

115107
void addNotificationReceiver(DocumentUpdateNotificationReceiver Receiver) {
@@ -133,7 +125,7 @@ class CursorInfoTest : public ::testing::Test {
133125
TestCursorInfo getCursor(const char *DocName, unsigned Offset,
134126
ArrayRef<const char *> CArgs) {
135127
auto Args = makeArgs(DocName, CArgs);
136-
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
128+
Semaphore sema(0);
137129

138130
TestCursorInfo TestInfo;
139131
getLang().getCursorInfo(DocName, Offset, Args,
@@ -142,40 +134,15 @@ class CursorInfoTest : public ::testing::Test {
142134
TestInfo.Typename = Info.TypeName;
143135
TestInfo.Filename = Info.Filename;
144136
TestInfo.DeclarationLoc = Info.DeclarationLoc;
145-
dispatch_semaphore_signal(sema);
137+
sema.signal();
146138
});
147139

148-
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60);
149-
bool expired = dispatch_semaphore_wait(sema, when);
140+
bool expired = sema.wait(60 * 1000);
150141
if (expired)
151142
llvm::report_fatal_error("check took too long");
152-
dispatch_release(sema);
153143
return TestInfo;
154144
}
155145

156-
void checkCursorAsync(const char *DocName, unsigned Offset,
157-
ArrayRef<const char *> CArgs,
158-
StringRef ExpectedName, StringRef ExpectedTypename) {
159-
auto Args = makeArgs(DocName, CArgs);
160-
++NumTasks;
161-
getLang().getCursorInfo(DocName, Offset, Args,
162-
[this, ExpectedName, ExpectedTypename](const CursorInfo &Info) {
163-
EXPECT_EQ(ExpectedName, Info.Name);
164-
EXPECT_EQ(ExpectedTypename, Info.TypeName);
165-
166-
int Num = --NumTasks;
167-
if (Num == 0)
168-
dispatch_semaphore_signal(TaskSema);
169-
});
170-
}
171-
172-
void waitForChecks() {
173-
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60);
174-
bool expired = dispatch_semaphore_wait(TaskSema, when);
175-
if (expired)
176-
llvm::report_fatal_error("checks took too long");
177-
}
178-
179146
unsigned findOffset(StringRef Val, StringRef Text) {
180147
auto pos = Text.find(Val);
181148
assert(pos != StringRef::npos);

0 commit comments

Comments
 (0)