Update PCH handling (#172)
This commit is contained in:
@@ -31,9 +31,7 @@ public:
|
||||
|
||||
class Guard {
|
||||
public:
|
||||
Guard(Lock* lock) : lock(lock) {
|
||||
assert(lock->locked && "Guard: should be locked");
|
||||
}
|
||||
Guard(Lock* lock) : lock(lock) {}
|
||||
|
||||
Guard(Guard&& other) : lock(other.lock) {
|
||||
other.lock = nullptr;
|
||||
@@ -58,12 +56,19 @@ public:
|
||||
/// Try to get the lock. If the lock is locked, the current coroutine will be
|
||||
/// suspended and wait for the lock to be released.
|
||||
Task<Guard> try_lock() {
|
||||
/// Note that this task also may be canceled, we make sure
|
||||
/// even cancel, it can resume one task(through destructor).
|
||||
Guard guard(this);
|
||||
|
||||
if(locked) {
|
||||
co_await awaiter::lock{awaiters};
|
||||
}
|
||||
|
||||
locked = true;
|
||||
co_return Guard{this};
|
||||
|
||||
/// Use `std::move` to make sure it will not resume
|
||||
/// the awaiter here.
|
||||
co_return std::move(guard);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,7 +18,7 @@ void listen(Callback callback);
|
||||
/// Listen on the given ip and port, callback is called when there is a LSP message available.
|
||||
void listen(const char* ip, unsigned int port, Callback callback);
|
||||
|
||||
/// Spawn a new process and listen on its stdin/stdout.
|
||||
/// FIXME: Spawn a new process and listen on its stdin/stdout.
|
||||
void spawn(llvm::StringRef path, llvm::ArrayRef<std::string> args, Callback callback);
|
||||
|
||||
/// Write a JSON value to the client.
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <source_location>
|
||||
|
||||
#include "Support/Format.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
|
||||
namespace clice::async {
|
||||
|
||||
@@ -24,10 +23,15 @@ struct promise_base {
|
||||
|
||||
/// The coroutine handle will be destroyed when the task is done or cancelled.
|
||||
Disposable = 1 << 1,
|
||||
|
||||
/// The coroutine is done or is cancelled and resumed, means it will never
|
||||
/// scheduled again.
|
||||
Finished = 1 << 2,
|
||||
};
|
||||
|
||||
/// The address of the actual coroutine handle and flags.
|
||||
llvm::PointerIntPair<void*, 2, Flags> data;
|
||||
uint8_t flags;
|
||||
|
||||
void* data;
|
||||
|
||||
/// The coroutine handle that is waiting for the task to complete.
|
||||
/// If this is a top-level coroutine, it is empty.
|
||||
@@ -39,12 +43,12 @@ struct promise_base {
|
||||
|
||||
template <typename Promise>
|
||||
void set(std::coroutine_handle<Promise> handle) {
|
||||
data.setInt(Empty);
|
||||
data.setPointer(handle.address());
|
||||
flags = Empty;
|
||||
data = handle.address();
|
||||
}
|
||||
|
||||
auto handle() const noexcept {
|
||||
return std::coroutine_handle<>::from_address(data.getPointer());
|
||||
return std::coroutine_handle<>::from_address(data);
|
||||
}
|
||||
|
||||
void schedule();
|
||||
@@ -60,21 +64,29 @@ struct promise_base {
|
||||
void cancel() {
|
||||
auto p = this;
|
||||
while(p) {
|
||||
p->data.setInt(Flags(data.getInt() | Flags::Cancelled));
|
||||
p->flags |= Flags::Cancelled;
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
bool cancelled() const noexcept {
|
||||
return data.getInt() & Flags::Cancelled;
|
||||
return flags & Flags::Cancelled;
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
data.setInt(Flags(data.getInt() | Flags::Disposable));
|
||||
flags |= Flags::Disposable;
|
||||
}
|
||||
|
||||
bool disposable() const noexcept {
|
||||
return data.getInt() & Flags::Disposable;
|
||||
return flags & Flags::Disposable;
|
||||
}
|
||||
|
||||
void finish() {
|
||||
flags |= Flags::Finished;
|
||||
}
|
||||
|
||||
bool finished() {
|
||||
return flags & Flags::Finished;
|
||||
}
|
||||
|
||||
std::coroutine_handle<> resume_handle() {
|
||||
@@ -83,11 +95,16 @@ struct promise_base {
|
||||
auto p = this;
|
||||
while(p && p->cancelled()) {
|
||||
auto con = p->continuation;
|
||||
|
||||
if(p->disposable()) {
|
||||
p->destroy();
|
||||
} else {
|
||||
p->finish();
|
||||
}
|
||||
|
||||
p = con;
|
||||
}
|
||||
|
||||
return std::noop_coroutine();
|
||||
} else {
|
||||
/// Otherwise, resume the coroutine handle.
|
||||
@@ -121,6 +138,9 @@ struct final {
|
||||
handle = continuation->resume_handle();
|
||||
}
|
||||
|
||||
/// Mark current coroutine as finished.
|
||||
current.promise().finish();
|
||||
|
||||
if(current.promise().disposable()) {
|
||||
/// If this task is disposable, destroy the coroutine handle.
|
||||
current.destroy();
|
||||
@@ -270,12 +290,20 @@ public:
|
||||
core.promise().cancel();
|
||||
}
|
||||
|
||||
bool cancelled() {
|
||||
return core.promise().cancelled();
|
||||
}
|
||||
|
||||
/// Dispose the task, it will be destroyed when finished or cancelled.
|
||||
void dispose() {
|
||||
core.promise().dispose();
|
||||
core = nullptr;
|
||||
}
|
||||
|
||||
bool finished() {
|
||||
return core.promise().finished();
|
||||
}
|
||||
|
||||
T result() {
|
||||
if constexpr(!std::is_void_v<T>) {
|
||||
return std::move(core.promise().value.value());
|
||||
|
||||
@@ -74,4 +74,6 @@ void init();
|
||||
|
||||
void run();
|
||||
|
||||
void stop();
|
||||
|
||||
} // namespace clice::async
|
||||
|
||||
Reference in New Issue
Block a user