Okay, so these are my errors.
std::invoke: no matching overloaded function found
// and
Failed to specialize function template 'unkown-type std::invoke("Callable &&,_Types &&...) noexcept()'
I really need your guys help. Im pretty new to C++, so I would like if you gave me examples on how to do it. Not only explain.
And this is my code:
#include <iostream>
#include <thread>
#include <stdio.h>
#include <Windows.h>
#include <string>
using namespace std;
void SetColor(int ForgC);
void Navigation();
void Switch(int index);
void UpdateMenu();
const int IWAL = 1;
const int ITRI = 0;
int M_Index = 0;
int Changes = 0;
bool Name1 = false;
bool Name2 = false;
string bools[2] = { "[OFF]", "[ON]" };
void Navigation()
{
for (;;)
{
for (int i = 2; i < 180; i++)
{
if (GetAsyncKeyState(i) & 0x8000)
{
switch (i)
{
case 38:
if (M_Index < 2)
M_Index++;
Changes++;
break;
case 40:
if (M_Index > 0)
M_Index--;
Changes++;
break;
case 37:
Switch(M_Index);
Changes++;
break;
case 39:
Switch(M_Index);
Changes++;
break;
}
Sleep(200);
}
}
}
}
void Switch(int index)
{
if (index == IWAL)
{
Name1 = !Name1;
}
else if (index == ITRI)
{
Name2 = !Name2;
}
}
void UpdateMenu()
{
int temp = -1;
for (;;)
{
if (temp != Changes)
{
temp = Changes;
system("cls");
SetColor(15);
cout << ">> Krizzo's Menu <<" << endl;
cout << "___________________" << endl << endl;
if (M_Index == IWAL)
{
SetColor(10);
cout << " Name1\t=\t" << bools[Name1] << endl;
}
else
{
SetColor(15);
cout << " Name1\t=\t" << bools[Name1] << endl;
}
if (M_Index == ITRI)
{
SetColor(10);
cout << " Name2\t=\t" << bools[Name2] << endl;
}
else
{
SetColor(15);
cout << " Name2\t=\t" << bools[Name2] << endl;
}
}
}
}
void SetColor(int ForgC)
{
WORD wColor;
//We will need this handle to get the current background attribute
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
//We use csbi for the wAttributes word.
if (GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//Mask out all but the background attribute, and add in the foreground color
wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
SetConsoleTextAttribute(hStdOut, wColor);
}
return;
}
int main(int argc, char** argv) {
std::thread t1(Navigation);
std::thread t2(Switch);
std::thread t3(UpdateMenu);
std::thread t4(SetColor);
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
Your Switch and SetColor functions take a parameter. You have to pass this parameter to the thread constructor. Example:
int addOne(int x)
{
return x + 1;
}
int main()
{
std::thread t1(addOne, 5);
t1.join();
}
When dealing with reference parameters, you have to wrap the parameter in a std::ref() call:
void addOne(int& x)
{
x += 1;
}
int main()
{
int a = 42;
std::thread t1(addOne, std::ref(a));
t1.join();
}
Lastly, when you want to run a member function of a class on a seperate thread, you have to pass the this pointer, as the thread has to know which instance the member function is called on.
class X
{
void doSomething()
{
std::thread t1(X::expensiveCalculations, this);
//do something else
t1.join();
}
void expensiveCalculations()
{
}
};
int main()
{
X x;
x.doSomething();
}
Related
I have 2 void functions and a main func.
But since first function has while(true) it works always and due to that second is not working. How to make it work all together at the same time?
void shoot()
{
*(DWORD*)(val.gameModule + offsets.ForceAttack, 5);
Sleep(5000);
*(DWORD*)(val.gameModule + offsets.ForceAttack, 4);
}
void bunny()
{
val.gameModule = (DWORD)GetModuleHandle("client_panorama.dll");
std::cout << (GetModuleHandle("client_panorama.dll")) << std::endl;;
val.localPlayer = *(DWORD*)(val.gameModule + offsets.lplayer);
while (true)
{
if (bunnyON == 1);
else
return;
val.flag = *(BYTE*)(val.localPlayer + offsets.flags);
if (isMoving())
if (GetAsyncKeyState(VK_SPACE) && val.flag & (1 << 0))
* (DWORD*)(val.gameModule + offsets.jump) = 6;
}
}
int main()
{
bunny();
shoot();
}
`
Try to do this, and check if this is what you need:
#include <thread>
void shoot()
{
*(DWORD*)(val.gameModule + offsets.ForceAttack, 5);
Sleep(5000);
*(DWORD*)(val.gameModule + offsets.ForceAttack, 4);
}
void bunny()
{
val.gameModule = (DWORD)GetModuleHandle("client_panorama.dll");
std::cout << (GetModuleHandle("client_panorama.dll")) << std::endl;;
val.localPlayer = *(DWORD*)(val.gameModule + offsets.lplayer);
while (true)
{
if (bunnyON == 1);
else
return;
val.flag = *(BYTE*)(val.localPlayer + offsets.flags);
if (isMoving())
if (GetAsyncKeyState(VK_SPACE) && val.flag & (1 << 0))
* (DWORD*)(val.gameModule + offsets.jump) = 6;
}
}
int main()
{
std::thread t1(bunny);
std::thread t2(shoot);
t1.join();
t2.join();
return 0;
}
My application start the logThread thread and then cyclically calls lookForSms wich makes a curl call and wait for logThread to read a certain string, but this string may never come so i used a condition_variable wait_for so that eventually (after 5 minutes) it can continue the test.
The problem is at times it waits a lot longer, sometimes 20 min sometimes forever.
How can I make it reliably work?
I'm using Visual Studio Community 2017, here the code:
void lookForSms(CURL *curl) {
sms_found = false;
int i;
CURLcode res;
cout << "\n" << timestamp() << "\t";
res = curl_easy_perform(curl);
if (res == CURLE_OK) {
unique_lock<mutex> lk(F);
analysis << timestampMil() << "\t";
while (cv.wait_for(lk, TIMEOUT_SMS * 1000ms) != cv_status::timeout && !sms_found);
if (sms_found) {
analysis << timestampMil() << "\tSMS RECEIVED\n";
cout << "\tOK";
}
else {
analysis << timestampMil() << "\tSMS LOST\n";
cout << "\tKO";
}
}
}
void logThread() {
string line;
int n, i, count;
unsigned char buf[BUFFER];
while (!close) {
N.lock();
M.lock();
N.unlock();
n = RS232_PollComport(comport, buf, BUFFER);
if (n > 0 && n < BUFFER) {
buf[n] = '\0';
for (i = 0; i < n; i++) {
if (buf[i] == '\n') {
all << timestampMil() << "\t" << line << "\n";
handleLine(line);
line = string();
}
else if (buf[i] != '\r' && buf[i] >= 32) {
line += buf[i];
}
}
}
M.unlock();
}
}
void handleLine(string line) {
if (searchString(line, RCV_SMS)) {
unique_lock<mutex> lk(F);
sms_found = true;
lk.unlock();
cv.notify_all();
}
}
[EDIT] This should have everything it needs to recreate the problem.
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#define TIMEOUT_SMS 300
#define DELAY_SMS 10
mutex L, M, N, F;
condition_variable cv;
void logThread() {
while (!close) {
N.lock();
M.lock();
N.unlock();
handleLine("");
Sleep(500);
M.unlock();
}
}
void lookForSms() {
unique_lock<mutex> lk(F);
sms_found = false;
unlocked = false;
//while (cv.wait_for(lk, TIMEOUT_SMS * 1000ms) != cv_status::timeout && !unlocked);
cv.wait_for(lk, 10 * TIMEOUT_SMS * 1000ms, []() {return unlocked; });
if (sms_found) {
cout << "\tOK";
}
else {
cout << "\tKO";
}
}
}
void handleLine(string line) {
if (false) {// the problem is when cv remains locked
unique_lock<mutex> lk(F);
unlocked = true;
sms_found = true;
lk.unlock();
cv.notify_all();
}
}
void stopThreads() {
N.lock();
M.lock();
//stop log thread
close = true;
N.unlock();
M.unlock();
}
int main(int argc, const char * argv[]) {
thread logger(logThread);
for (i = 0; i < repeat; i++) {
lookForSms();
Sleep(DELAY_SMS * 1000);
}
//aquire mutex and set close to true, then join
stopThreads();
//wait for the thread to end
logger.join();
return 0;
}
I'm studying ZeroMQ with myself.
I tested PUB as a server(bind), SUB as a client(connect) and worked fine. Opposite (PUB as a client(connect), SUB as a server(bind)) also works fine.
When I connect a another SUB socket as client something goes wrong without any exception or errors.
here's my example code.
#include <zmq.hpp>
#include <string>
#include <iostream>
#include <unistd.h>
#include <thread>
class ZMQSock
{
public:
ZMQSock(const char* addr)
{
if (addr != NULL)
{
mctx = new zmq::context_t(1);
mszAddr = new char[strlen(addr) + 1];
snprintf(mszAddr, strlen(addr) + 1, "%s", addr);
}
}
virtual ~ZMQSock()
{
if (msock != nullptr)
delete msock;
if (mctx != nullptr)
delete mctx;
if (mszAddr != nullptr)
delete [] mszAddr;
}
int zbind()
{
if (msock != nullptr)
msock->bind(mszAddr);
else return -1;
return 0;
}
int zconnect()
{
if (msock != nullptr)
msock->connect(mszAddr);
else return -1;
return 0;
}
void start()
{
if (mbthread != false)
return ;
mbthread = true;
mhthread = std::thread(std::bind(&ZMQSock::run, this));
}
virtual void stop()
{
if (mbthread == false)
return ;
mbthread = false;
if (mhthread.joinable())
mhthread.join();
}
virtual void run() = 0;
protected:
char* mszAddr{nullptr};
zmq::context_t* mctx{nullptr};
zmq::socket_t* msock{nullptr};
bool mbthread{false};
std::thread mhthread;
};
class ZPublisher : public ZMQSock
{
public:
ZPublisher(const char* addr) : ZMQSock(addr)
{
if (msock == nullptr)
{
msock = new zmq::socket_t(*mctx, ZMQ_PUB);
}
}
virtual ~ZPublisher()
{
}
bool zsend(const char* data, const unsigned int length, bool sendmore=false)
{
zmq::message_t msg(length);
memcpy(msg.data(), data, length);
if (sendmore)
return msock->send(msg, ZMQ_SNDMORE);
return msock->send(msg);
}
void run()
{
if (mszAddr == nullptr)
return ;
if (strlen(mszAddr) < 6)
return ;
const char* fdelim = "1";
const char* first = "it sends to first. two can not recv this sentence!\0";
const char* sdelim = "2";
const char* second = "it sends to second. one can not recv this sentence!\0";
while (mbthread)
{
zsend(fdelim, 1, true);
zsend(first, strlen(first));
zsend(sdelim, 1, true);
zsend(second, strlen(second));
usleep(1000 * 1000);
}
}
};
class ZSubscriber : public ZMQSock
{
public:
ZSubscriber(const char* addr) : ZMQSock(addr)
{
if (msock == nullptr)
{
msock = new zmq::socket_t(*mctx, ZMQ_SUB);
}
}
virtual ~ZSubscriber()
{
}
void setScriberDelim(const char* delim, const int length)
{
msock->setsockopt(ZMQ_SUBSCRIBE, delim, length);
mdelim = std::string(delim, length);
}
std::string zrecv()
{
zmq::message_t msg;
msock->recv(&msg);
return std::string(static_cast<char*>(msg.data()), msg.size());
}
void run()
{
if (mszAddr == nullptr)
return ;
if (strlen(mszAddr) < 6)
return ;
while (mbthread)
{
std::cout << "MY DELIM IS [" << mdelim << "] - MSG : ";
std::cout << zrecv() << std::endl;
usleep(1000 * 1000);
}
}
private:
std::string mdelim;
};
int main ()
{
ZPublisher pub("tcp://localhost:5252");
ZSubscriber sub1("tcp://localhost:5252");
ZSubscriber sub2("tcp://*:5252");
pub.zconnect();
sub1.zconnect();
sub2.zbind();
sub1.setScriberDelim("1", 1);
sub2.setScriberDelim("2", 1);
pub.start();
std::cout << "PUB Server has been started.." << std::endl;
usleep(1000 * 1000);
sub1.start();
std::cout << "SUB1 Start." << std::endl;
sub2.start();
std::cout << "SUB2 Start." << std::endl;
int i = 0;
std::cout << "< Press any key to exit program. >" << std::endl;
std::cin >> i;
std::cout << "SUB1 STOP START" << std::endl;
sub1.stop();
std::cout << "SUB2 STOP START" << std::endl;
sub2.stop();
std::cout << "PUB STOP START" << std::endl;
pub.stop();
std::cout << "ALL DONE" << std::endl;
return 0;
}
What causes this? or Am I using PUB/SUB illegally?
You are connecting a SUB socket to a SUB socket, that is an invalid connection. In your case the PUB should bind and the SUBs should connect.
I already succeeded when trying to connect a client to a server. But the server was using the loopback ip address. How is it possible to make a server using SDLNet so that i can access it from any computer that is connected to any network?
The problem is the code because I don't find any place where I can define another IP address for the server...
Here is the code for the server:
#include "Link\SDL\include\SDL.h"
#include "Link\SDL\include\SDL_net.h"
#include <iostream>
#include <vector>
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDLNet_Init();
int curid=2;
int playernum = 0;
char data[1400];
bool running=true;
SDL_Event event;
IPaddress ip;
SDLNet_ResolveHost(&ip,NULL,1234);
SDLNet_SocketSet sockets=SDLNet_AllocSocketSet(30); //max player
std::vector<TCPsocket> socketsvector;
TCPsocket server=SDLNet_TCP_Open(&ip);
while(running)
{
while(SDL_PollEvent(&event))
{
if(event.type==SDL_QUIT || event.type==SDL_KEYDOWN && event.key.keysym.sym==SDLK_ESCAPE)
{
running=false;
break;
}
}
TCPsocket tmpsocket=SDLNet_TCP_Accept(server);
if(tmpsocket)
{
if(playernum<30)
{
SDLNet_TCP_AddSocket(sockets,tmpsocket);
socketsvector.push_back(tmpsocket);
sprintf(data,"0 %d \n",curid);
curid++;
playernum++;
std::cout << "new connection. ID: " << curid << std::endl;
}
else
{
sprintf(data,"3 \n"); //server is full
}
SDLNet_TCP_Send(tmpsocket,data,strlen(data)+1);
}
while(SDLNet_CheckSockets(sockets,0) > 0)
{
for(int i=0;i<socketsvector.size();i++)
{
if(SDLNet_SocketReady(socketsvector[i])==1)
{
SDLNet_TCP_Recv(socketsvector[i],data,1400);
int num=data[0]-'0';
int j=1;
while(data[j]>='0' && data[j]<='9')
{
num*=10;
num+=data[j]-'0';
j++;
}
if(num==1)
{
for(int k=0;k<socketsvector.size();k++)
{
if(k==i)
continue;
SDLNet_TCP_Send(socketsvector[k],data,strlen(data)+1);
}
}else if(num==2)
{
for(int k=0;k<socketsvector.size();k++)
{
if(k==i)
continue;
SDLNet_TCP_Send(socketsvector[k],data,strlen(data)+1);
}
SDLNet_TCP_DelSocket(sockets,socketsvector[i]);
SDLNet_TCP_Close(socketsvector[i]);
socketsvector.erase(socketsvector.begin()+i);
playernum--;
std::cout << "connection closed..." << std::endl;
std::cout << playernum << " players in server" << std::endl;
}
}
}
}
//SDL_Delay(30);
}
SDLNet_TCP_Close(server);
SDLNet_FreeSocketSet(sockets);
SDLNet_Quit();
SDL_Quit();
return 0;
}
Ok, and here is the code for the client...
class network{
private:
SDLNet_SocketSet sockets;
TCPsocket connection;
char data[1400];
public:
network(const char* ip);
~network();
void send(Player* p);
void receive(std::vector<Enemy*>& enemies, Player* p); //std::vector<unsigned int>& f,std::vector<enemy*>& enemies,std::vector<weapon*> weapons,player* p
void closeConnection();
};
network::network(const char* ipaddress)
{
SDLNet_Init();
IPaddress ip;
if(SDLNet_ResolveHost(&ip,ipaddress,1234)==-1)
std::cout << "error while resolving the host (bad ip?)" << std::endl;
connection=SDLNet_TCP_Open(&ip);
sockets=SDLNet_AllocSocketSet(1);
if(sockets==NULL)
std::cout << "error while connecting (bad ip?)" << std::endl;
SDLNet_TCP_AddSocket(sockets,connection);
}
void network::closeConnection()
{
SDLNet_TCP_Send(connection,"2 \n",4); //close with the server
}
network::~network()
{
SDLNet_TCP_Close(connection);
SDLNet_FreeSocketSet(sockets);
SDLNet_Quit();
}
void network::send(Player* p)
{
vector3d vec=p->cam.getVector();
//1 curframe position rotation lookdirection health curweaponnum
sprintf(data,"1 %d %f %f %f %f %f %f \n",p->id, p->cam.getLocation().x,p->cam.getLocation().y,p->cam.getLocation().z,vec.x,vec.y,vec.z);
int size=0;
int len=strlen(data)+1;
//SDLNet_TCP_Send(connection,data,len);
while(size<len)
{
size+=SDLNet_TCP_Send(connection,data+size,len-size);
}
}
void network::receive(std::vector<Enemy*>& enemies, Player* p) //std::vector<unsigned int>& f,std::vector<enemy*>& enemies,std::vector<weapon*> weapons,player* p
{
SDLNet_CheckSockets(sockets,10);
if(SDLNet_SocketReady(connection))
{
int tmp,num;
int offset=0;
do
{
offset=SDLNet_TCP_Recv(connection,(char*)data+(offset),1400);
if(offset<=0)
return;
}while(data[strlen(data)-1]!='\n');
sscanf(data,"%d %d",&num,&tmp);
//cout << num << " " << tmp << endl;
cout << data << endl;
int i=0;
if(num == 0)
{
p->setId(tmp);
}
else if(num==1)
{
bool NewEnemy = true;
for(i=0;i<enemies.size();i++)
{
if(enemies[i]->id == tmp)
{
int nothing;
sscanf(data,"1 %d %f %f %f %f %f %f \n",¬hing, &(enemies[i]->position.x),&(enemies[i]->position.y),&(enemies[i]->position.z),&(enemies[i]->rotation.x),&(enemies[i]->rotation.y),&(enemies[i]->rotation.z));
NewEnemy = false;
break;
}
}
if(NewEnemy == true && tmp != 0)
{
std::cout << "pusing new enemy" << std::endl;
enemies.push_back(new Enemy(tmp));
}
}
else if(num == 2)
{
for(int k = 0; k < enemies.size(); k++)
{
if(enemies[k]->id == tmp)
{
enemies.erase(enemies.begin() + k);
}
}
}
else if(num == 3)
{
std::cout << "Could not connect. Server is full." << std::endl;
}
}
}
If you can see, I type the IP address for the client when the program starts. But the only value that works is the loopback address.
I wrote a code to implement spin lock and mutex lock.
There is an interesting but. A magic cout can keep my program alive. If I remove the cout, my program will be sleeping forever. (This only happens in Linux. Windows is doing fine)
Any one have a clue?
#include <pthread.h>
#include <iostream>
#include <queue>
#include <sys/time.h>
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define Tcount 10
#define TheLock MutexLock
static inline int TAS(volatile int * ptr) {
unsigned long result;
asm volatile("lock;"
"xchgl %0, %1;"
: "=r"(result), "=m"(*ptr)
: "0"(1), "m"(*ptr)
: "memory");
return result;
}
class SpinLock {
private:
int lock;
pthread_t owner;
public:
SpinLock() {
lock = 0;
}
void getLock() {
while (TAS(&lock) == 1) {
}
owner = pthread_self();
}
void releaseLock() {
if (lock == 0) {
cout << "Spin no lock" << endl;
return;
} else if (owner == pthread_self()) {
owner = NULL;
lock = 0;
} else {
throw runtime_error("Spin can't release");
}
}
};
class MutexLock {
private:
int lock;
pthread_t owner;
queue<pthread_t> q;
SpinLock qLock;
public:
MutexLock() {
lock = 0;
}
void getLock(int id) {
pthread_t self = pthread_self();
cout<<"a"<<endl;// magic cout
if (TAS(&lock) == 0) {
owner = self;
return;
}
qLock.getLock();
q.push(self);
qLock.releaseLock();
while (owner != self) {
}
}
void releaseLock(int id) {
if (lock == 0) {
cout << "Mutex no lock" << endl;
return;
} else if (owner == pthread_self()) {
qLock.getLock();
if (q.empty()) {
owner = NULL;
lock = 0;
} else {
owner = q.front();
q.pop();
}
qLock.releaseLock();
} else {
throw runtime_error("Mutex can't release");
}
}
};
TheLock lock;
int g = 0;
void* run(void* pt) {
int id = (int) pt;
for (int i = 0; i < 10000; i++) {
lock.getLock(id);
//cout<<"Thread "<<id<<" get lock, g="<<g<<endl;
int next = g + 1;
g = next;
//cout<<"Thread "<<id<<" release lock, g="<<g<<endl;
lock.releaseLock(id);
}
return NULL;
}
int main() {
pthread_t th[Tcount];
long mtime, seconds, useconds;
struct timeval start, end;
gettimeofday(&start, NULL);
for (int i = 0; i < Tcount; i++) {
pthread_create(&th[i], NULL, run, (void*) (i+10));
}
for (int i = 0; i < Tcount; i++) {
pthread_join(th[i], 0);
}
gettimeofday(&end, NULL);
seconds = end.tv_sec - start.tv_sec;
useconds = end.tv_usec - start.tv_usec;
mtime = ((seconds) * 1000000 + useconds);
cout << "g=" << g << endl;
cout << "time=" << mtime << endl;
return 0;
}
You cannot implement a mutex by using the volatile keyword as the operations may not be atomic. This means that the OS might switch to a different thread before the operation has completed.
For mutex you have to use the OS. It is the only thing that knows when threads are being switched.