Skip to content

Instantly share code, notes, and snippets.

@sgtcortez
Created April 21, 2022 00:47
Show Gist options
  • Save sgtcortez/3bd46c378391383ce91be82e2dd5db71 to your computer and use it in GitHub Desktop.
Save sgtcortez/3bd46c378391383ce91be82e2dd5db71 to your computer and use it in GitHub Desktop.
This is a very simple implementation of a semaphore using c++, just for learning purposes
#include "Semaphore.hpp"
#include <chrono>
#include <condition_variable>
#include <cstdint>
#include <iostream>
#include <string>
#include <thread>
using namespace std;
using namespace ramboindustries;
void acquire(Semaphore& semaphore)
{
this_thread::sleep_for(std::chrono::seconds(3));
semaphore.acquire();
cout << this_thread::get_id() << " says: I Got it !!!" << endl;
this_thread::sleep_for(std::chrono::seconds(10));
cout << this_thread::get_id() << " says: I am going to release it now!" << endl;
semaphore.release();
}
int main(int argc, char** argv)
{
if (argc != 3)
{
cerr << "Usage: " << argv[0] << " <threads-number> <permits-number> " << endl;
return 1;
}
const std::uint16_t threads_number = std::atoi(argv[1]);
const std::uint16_t permits_number = std::atoi(argv[2]);
Semaphore semaphore(permits_number);
thread threads[threads_number];
for (auto index = 0; index < sizeof(threads) / sizeof(threads[0]); index++)
{
threads[index] = thread(acquire, ref(semaphore));
}
for (auto& thread: threads)
{
thread.join();
}
cout << "Done ..." << endl;
return 0;
}
CPP_C=clang++
C_FLAGS=-std=c++14 -g
BINARY=Main.out
LINK=-lpthread
OBJECTS=\
Semaphore.o
all: $(BINARY)
Semaphore.o: Semaphore.cpp Semaphore.hpp
@$(CPP_C) -c $(C_FLAGS) Semaphore.cpp
$(BINARY): Main.cpp $(OBJECTS)
@$(CPP_C) $(C_FLAGS) -o $@ Main.cpp $(LINK) $(OBJECTS)
clear:
@rm -Rf *.o *.out 1>/dev/null 2>&1
#include "Semaphore.hpp"
#include "Semaphore.hpp"
#include <cstdint>
#include <mutex>
#include <iostream>
#include <thread>
#include <string>
using namespace std;
ramboindustries::Semaphore::Semaphore(const std::uint16_t permits) noexcept
: initial_permits(permits)
{
cout << "Initialized semaphore with: " << to_string(permits) << " permits ..." << endl;
this->permits = permits;
}
void ramboindustries::Semaphore::acquire() noexcept
{
cout << "Thread: " << this_thread::get_id() << " is trying to acquire a permit" << endl;
auto lock = unique_lock<std::mutex>(mutex);
if (permits == 0)
{
cout << "No permits avaialable ... " << " Thread: " << this_thread::get_id() << " is going to wait ..." << endl;
condition.wait(lock);
}
cout << "Thread: " << this_thread::get_id() << " got a permit ..." << endl;
permits--;
}
void ramboindustries::Semaphore::release() noexcept
{
cout << "Thread: " << this_thread::get_id() << " is releasing the permit ..." << endl;
auto lock = std::unique_lock<std::mutex>(mutex);
permits++;
condition.notify_one();
}
std::uint16_t ramboindustries::Semaphore::get_initial_permits() const noexcept
{
return initial_permits;
}
std::uint16_t ramboindustries::Semaphore::get_permits() const noexcept
{
return permits;
}
ramboindustries::BinarySemaphore::BinarySemaphore() noexcept
: Semaphore(1)
{
}
#pragma once
#include <cstdint>
#include <condition_variable>
#include <mutex>
namespace ramboindustries {
class Semaphore
{
private:
const std::uint16_t initial_permits;
std::uint16_t permits;
std::mutex mutex;
std::condition_variable condition;
public:
Semaphore(const std::uint16_t permits) noexcept;
void acquire() noexcept;
void release() noexcept;
std::uint16_t get_initial_permits() const noexcept;
std::uint16_t get_permits() const noexcept;
};
class BinarySemaphore : public Semaphore
{
public:
BinarySemaphore() noexcept;
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment