Ninja
jobserver-win32.cc
Go to the documentation of this file.
1 // Copyright 2024 Google Inc. All Rights Reserved.
2 //
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 <assert.h>
16 #include <windows.h>
17 
18 #include "jobserver.h"
19 #include "util.h"
20 
21 namespace {
22 
23 // Implementation of Jobserver::Client for Win32 systems.
24 // At the moment, only the semaphore scheme is supported,
25 // even when running under Cygwin which could support the
26 // pipe version, in theory.
27 class Win32JobserverClient : public Jobserver::Client {
28  public:
29  virtual ~Win32JobserverClient() {
30  // NOTE: OpenSemaphore() returns NULL on failure.
31  if (IsValid()) {
32  ::CloseHandle(handle_);
33  }
34  }
35 
36  Jobserver::Slot TryAcquire() override {
37  if (IsValid()) {
38  if (has_implicit_slot_) {
39  has_implicit_slot_ = false;
41  }
42 
43  DWORD ret = ::WaitForSingleObject(handle_, 0);
44  if (ret == WAIT_OBJECT_0) {
45  // Hard-code value 1 for the explicit slot value.
47  }
48  }
49  return Jobserver::Slot();
50  }
51 
52  void Release(Jobserver::Slot slot) override {
53  if (!slot.IsValid())
54  return;
55 
56  if (slot.IsImplicit()) {
57  assert(!has_implicit_slot_ && "Implicit slot cannot be released twice!");
58  has_implicit_slot_ = true;
59  return;
60  }
61 
62  // Nothing can be done in case of error here.
63  (void)::ReleaseSemaphore(handle_, 1, NULL);
64  }
65 
66  bool InitWithSemaphore(const std::string& name, std::string* error) {
67  handle_ = ::OpenSemaphoreA(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, FALSE,
68  name.c_str());
69  if (handle_ == NULL) {
70  *error = "Error opening semaphore: " + GetLastErrorString();
71  return false;
72  }
73  return true;
74  }
75 
76  protected:
77  bool IsValid() const {
78  // NOTE: OpenSemaphore() returns NULL on failure, not INVALID_HANDLE_VALUE.
79  return handle_ != NULL;
80  }
81 
82  // Set to true if the implicit slot has not been acquired yet.
83  bool has_implicit_slot_ = true;
84 
85  // Semaphore handle. NULL means not in use.
86  HANDLE handle_ = NULL;
87 };
88 
89 } // namespace
90 
91 // static
92 std::unique_ptr<Jobserver::Client> Jobserver::Client::Create(
93  const Jobserver::Config& config, std::string* error) {
94  bool success = false;
95  auto client =
96  std::unique_ptr<Win32JobserverClient>(new Win32JobserverClient());
98  success = client->InitWithSemaphore(config.path, error);
99  } else {
100  *error = "Unsupported jobserver mode";
101  }
102  if (!success)
103  client.reset();
104  return client;
105 }
A Jobserver::Client instance models a client of an external GNU jobserver pool, which can be implemen...
Definition: jobserver.h:189
virtual Slot TryAcquire()
Try to acquire a slot from the pool.
Definition: jobserver.h:201
static std::unique_ptr< Client > Create(const Config &, std::string *error)
Create a new Client instance from a given configuration.
virtual void Release(Slot slot)
Release a slot to the pool.
Definition: jobserver.h:208
A Jobserver::Config models how to access or implement a GNU jobserver implementation.
Definition: jobserver.h:106
std::string path
For kModeFifo, this is the path to the Unix FIFO to use.
Definition: jobserver.h:146
Mode mode
Implementation mode for the pool.
Definition: jobserver.h:142
A Jobserver::Slot models a single job slot that can be acquired from.
Definition: jobserver.h:55
static Slot CreateImplicit()
Create instance for the implicit value.
Definition: jobserver.h:94
static Slot CreateExplicit(uint8_t value)
Create instance for explicit byte value.
Definition: jobserver.h:89
bool IsImplicit() const
Return true if this instance represents an implicit job slot.
Definition: jobserver.h:79
bool IsValid() const
Return true if this instance is valid, i.e.
Definition: jobserver.h:76