Skip to content

Instantly share code, notes, and snippets.

@rioki
Created January 21, 2015 10:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rioki/0ed85afc742020263975 to your computer and use it in GitHub Desktop.
Save rioki/0ed85afc742020263975 to your computer and use it in GitHub Desktop.
//
// Copyright (c) 2015 Sean Farrell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <iostream>
#include <string>
#include "WorkPool.h"
std::vector<std::string> get_ips(addrinfo* ai)
{
char buff[INET6_ADDRSTRLEN];
std::vector<std::string> result;
while (ai != nullptr)
{
switch (ai->ai_family)
{
case AF_INET:
{
sockaddr_in* ipv4 = (sockaddr_in*)ai->ai_addr;
result.push_back(inet_ntop(AF_INET, &ipv4->sin_addr, buff, INET6_ADDRSTRLEN));
break;
}
case AF_INET6:
{
sockaddr_in6* ipv6 = (sockaddr_in6*)ai->ai_addr;
result.push_back(inet_ntop(AF_INET, &ipv6->sin6_addr, buff, INET6_ADDRSTRLEN));
break;
}
default:
break;
}
ai = ai->ai_next;
}
return result;
}
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
WorkPool pool;
addrinfo* google_com = nullptr;
addrinfo* google_de = nullptr;
addrinfo* siemens_com = nullptr;
std::future<int> fgcom = pool.enqueue<int, PCSTR, PCSTR, const ADDRINFOA*, PADDRINFOA*>(getaddrinfo, "google.com", NULL, NULL, &google_com);
std::future<int> fgde = pool.enqueue<int, PCSTR, PCSTR, const ADDRINFOA*, PADDRINFOA*>(getaddrinfo, "google.de", NULL, NULL, &google_de);
std::future<int> fsi = pool.enqueue<int, PCSTR, PCSTR, const ADDRINFOA*, PADDRINFOA*>(getaddrinfo, "siemens.com", NULL, NULL, &siemens_com);
if (fgcom.get() == 0)
{
std::vector<std::string> ips = get_ips(google_com);
std::cout << "google.com: ";
for (unsigned int i = 0; i < ips.size(); i++)
{
std::cout << ips[i];
if (i != ips.size() -1)
{
std::cout << ", ";
}
}
std::cout << std::endl;
}
else
{
std::cout << "Failed to resolve google.com" << std::endl;
}
if (fgde.get() == 0)
{
std::vector<std::string> ips = get_ips(google_de);
std::cout << "google.de: ";
for (unsigned int i = 0; i < ips.size(); i++)
{
std::cout << ips[i];
if (i != ips.size() -1)
{
std::cout << ", ";
}
}
std::cout << std::endl;
}
else
{
std::cout << "Failed to resolve google.de" << std::endl;
}
if (fsi.get() == 0)
{
std::vector<std::string> ips = get_ips(siemens_com);
std::cout << "siemens.com: ";
for (unsigned int i = 0; i < ips.size(); i++)
{
std::cout << ips[i];
if (i != ips.size() -1)
{
std::cout << ", ";
}
}
std::cout << std::endl;
}
else
{
std::cout << "Failed to resolve siemens.com" << std::endl;
}
freeaddrinfo(google_com);
freeaddrinfo(google_de);
freeaddrinfo(siemens_com);
system("pause");
return 0;
}
//
// Copyright (c) 2015 Sean Farrell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "ThreadPool.h"
ThreadPool::~ThreadPool() {}
void ThreadPool::join()
{
for (auto& thread : threads)
{
thread.join();
}
}
void ThreadPool::detach()
{
for (auto& thread : threads)
{
thread.detach();
}
}
//
// Copyright (c) 2015 Sean Farrell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef _THREAD_POOL_
#define _THREAD_POOL_
#include <vector>
#include <thread>
class ThreadPool
{
public:
template <class Function, class... Args>
ThreadPool(unsigned int concurency, Function&& f, Args&&... args);
ThreadPool(const ThreadPool&) = delete;
~ThreadPool();
const ThreadPool& operator = (const ThreadPool&) = delete;
void join();
void detach();
private:
std::vector<std::thread> threads;
};
template <class Function, class... Args>
ThreadPool::ThreadPool(unsigned int concurency, Function&& f, Args&&... args)
: threads(concurency)
{
for (unsigned int i = 0; i < concurency; i++)
{
threads[i] = std::thread(f, args...);
}
}
#endif
//
// Copyright (c) 2015 Sean Farrell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "WorkPool.h"
WorkPool::WorkPool(unsigned int concurency)
: running(true),
threads(concurency, [this] {
std::unique_ptr<BasicTask> task;
while (running)
{
{
std::unique_lock<std::mutex> lock(mutex);
if (queue.empty())
{
work_cond.wait(lock);
}
// The queue may be empty, when shttuing down
if (! queue.empty())
{
task = std::move(queue.front());
queue.pop();
}
}
if (task)
{
task->execute();
}
task.release();
}
})
{
}
WorkPool::~WorkPool()
{
running = false;
work_cond.notify_all();
threads.join();
}
//
// Copyright (c) 2015 Sean Farrell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef _WORK_POOL_H_
#define _WORK_POOL_H_
#include <atomic>
#include <mutex>
#include <queue>
#include <memory>
#include <future>
#include "ThreadPool.h"
class WorkPool
{
public:
WorkPool(unsigned int concurency = std::thread::hardware_concurrency());
~WorkPool();
template <typename Res, typename ... Args, typename Fun>
std::future<Res> enqueue(Fun func, Args... args);
private:
struct BasicTask
{
virtual ~BasicTask() {};
virtual void execute() = 0;
};
template <typename Res>
struct Task : public BasicTask
{
std::packaged_task<Res ()> task;
Task(std::function<Res ()> func)
: task(func) {}
void execute()
{
task();
}
};
std::atomic<bool> running;
std::mutex mutex;
std::condition_variable work_cond;
std::queue<std::unique_ptr<BasicTask>> queue;
ThreadPool threads;
};
template <typename Res, typename ... Args, typename Fun>
std::future<Res> WorkPool::enqueue(Fun func, Args... args)
{
std::lock_guard<std::mutex> lock(mutex);
auto task = std::make_unique<Task<Res>>(std::bind(func, args...));
std::future<Res> f = task->task.get_future();
queue.push(std::move(task));
work_cond.notify_one();
return f;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment