Help c ++ threads Pause and Resume

0

I'm new to this c ++, this code I did practically with the help of internet pages.  I would like to know how I can pause and resume two threads, that when I start a thread A I reach a point where it stops, then the other thread B starts and reaches a point where it stops, then returns with thread A, and so on and so on. at the end show the results.

Here the code:

#include <cstdio>
#include<iostream> //std::cout
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include <condition_variable>
#include <fstream>
#include <cstdlib>
#include <math.h>
#include <limits.h>
#include <time.h>
#include <thread> //std::thread
#include <mutex>

int prime(long int);
void ce();
long int cd(long int);
void encrypt();
void decrypt();
void calculoPi();
void RSA();
void hacerArchivo();
void printPossibleValues();
string leerArchivo();

using namespace std;

long int p, q, n, t, flag, e[100], d[100], temp[100], j, m[100], en[100], i;
char msg[100];
char resp;
std::mutex mu;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
FILE *doc;
int numeroint = 0;
int salto = 0;
int porcentajetotal = 0;
int porcentajeB = 0;
int contadorDos = 0;
int iteradorDos = 0;
int cantIteracionesDos = 0;
int saltoDos = 0;
int porcentajeA = 0;
int porcentajeTempDos = 0;


int prime(long int pr) {
  int i;
  j = sqrt(pr);
  for (i = 2; i <= j; i++) {
    if (pr % i == 0)
      return 0;
  }
  return 1;
}


//http://stackoverflow.com/questions/15501681/suspend-and-resume-one-c-        thread-in-another
//Hilos calculo de Pi
void ThreadB_Activity()
{
  // Wait until ThreadA() sends data
  {
    std::unique_lock<std::mutex> lk(mu);
    cv.wait(lk, []{return ready;});
  }

  std::cout << "Thread B is processing data\n";
  data += " after processing";
  // Send data back to ThreadA through the condition variable
  {
    std::lock_guard<std::mutex> lk(mu);
    processed = true;
    std::cout << "Thread B signals data processing completed\n";
  }

  /*aqui hay que poner la jugada para que avance*/
  if (contadorDos == 0) {
    cout << "\nGETTING P & Q PRIME NUMBERS";
  }

  cout <<"\nPorcentaje de realización del Hilo B : " <<porcentajeA<<"% \n";
  porcentajeA =porcentajeA + porcentajeTempDos;
  cout<<"fin del hilo B\n";
  cv.notify_one();
}

//hiloRSA
void ThreadA_Activity()
{
  std::cout<<"Thread A started "<<std::endl;
  data = "Example data";
  // send data to the worker thread
  {
    std::lock_guard<std::mutex> lk(mu);
    ready = true;
    std::cout << "Thread A signals data are ready to be processed\n";
  }

  cout << "\nHilo RSA al : " << porcentajetotal << "% \n";
  porcentajetotal = porcentajetotal + porcentajeB;
  cv.notify_one();//notify to ThreadB that he can start doing his job

  // wait for the Thread B
  {
    std::unique_lock<std::mutex> lk(mu);
    cv.wait(lk, []{return processed;});
  }
  std::cout << "Back in Thread A , data = " << data << '\n';

  std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ));
  std::cout<<"end of Thread A"<<std::endl;
}

int main() { /* Explicacion de Hilos       http://www.cplusplus.com/reference/thread/thread/  */

  //Manejo de porcentajes de los hilos
  //25% 50% 75% 100%

  cout <<"Interaciones de 4 fases\n";
  cout <<"------------------------------------\n";
  numeroint = 4;
  porcentajetotal = 100 / numeroint;
  porcentajeA = porcentajetotal;
  porcentajeB = porcentajetotal;
  porcentajeA = porcentajeB;

  cout << "Valores de las interaciones\n";
  cout <<"------------------------------------\n";

  for (int i = 0; i < numeroint; i++) {

    std::thread ThreadB(ThreadB_Activity);
    std::thread ThreadA(ThreadA_Activity);

    ThreadB.join();
    ThreadA.join();
  }

  cout <<"------------------------------------\n";
  std::cout << "Back in main , data = " << data << '\n';
  cout <<"------------------------------------\n";

  cout << "\nHilos a ejecutarse\n";
  cout <<"------------------------------------\n";

  std::thread HiloB(calculoPi); //crea un nuevo hilo que se llama calculoPI
  std::thread HiloA(RSA); //crea un nuevo hilo que se llama RSA

  //http://www.cplusplus.com/reference/thread/thread/join/ */
  //Sincronizacion de hilos
  HiloB.join(); // lo pausa hasta que el primero termine
  HiloA.join(); //lo pausa hasta que el segundo termine

  std::cout << "Completado Pi y RSA\n";
  cout <<"------------------------------------\n";

  return 0;
}


void calculoPi() {
  // calcula el resultado de PI

  srand((unsigned int) time((time_t *) NULL));

  int in = 0, out = 0;
  double d, x, y, pi;
  long long cont = 10516267; // ou qualquer outro valor

  while (cont-- > 0) {

    x = (double) rand() / (double) INT_MAX;
    y = (double) rand() / (double) INT_MAX;

    d = x * x + y*y;

    (d <= 1.0) ? in++ : out++;

  }
  pi = 4.0 * (float) in / (float) (in + out);
  printf("\n");
  printf("pi (aproximado) = %2.30f\n", pi);

}

void RSA()
// Calculo del encriptado de rsa
//http://www.sanfoundry.com/cpp-program-implement-rsa-algorithm/
{

  p = 47;
  flag = prime(p);
  q = 53;
  flag = prime(q);

  cout << "\nOpteniendo mensaje desde el .TXT\n";
  fflush(stdin);

  // Se lee el txt
  ifstream fin("Archivo.txt");
  fin >> msg;


  for (i = 0; msg[i] != NULL; i++) {
    m[i] = msg[i];
  }

  n = p * q;
  t = (p - 1) * (q - 1);
  ce();
  printPossibleValues();
  encrypt();
  decrypt();
}

void printPossibleValues() {
  cout << "\nLos posible valores de E y D son\n";
  for (i = 0; i < j - 1; i++)
    cout << e[i] << "\t" << d[i] << "\n";
}

void ce()
{
  int k;
  k = 0;
  for (i = 2; i < t; i++)
  {
    if (t % i == 0)
      continue;

    flag = prime(i);
    if (flag == 1 && i != p && i != q)
    {
      e[k] = i;
      flag = cd(e[k]);
      if (flag > 0)
      {
        d[k] = flag;
        k++;
      }

      if (k == 99)
        break;
    }
  }
}

long int cd(long int x)
{
  long int k = 1;
  while (1)
  {
    k = k + t;
    if (k % x == 0)
      return (k / x);
  }
}

void encrypt()
{
  long int pt, ct, key = e[0], k, len;
  i = 0;
  len = strlen(msg);

  while (i != len)
  {
    pt = m[i];
    pt = pt - 96;
    k = 1;

    for (j = 0; j < key; j++)
    {
      k = k * pt;
      k = k % n;
    }

    temp[i] = k;
    ct = k + 96;
    en[i] = ct;
    i++;
  }

  en[i] = -1;

  cout << "\nEl mensaje encriptado es\n";

  for (i = 0; en[i] != -1; i++)
    printf("%c", en[i]);
}

void decrypt()
{
  long int pt, ct, key = d[0], k;
  i = 0;

  while (en[i] != -1)
  {
    ct = temp[i];
    k = 1;

    for (j = 0; j < key; j++)
    {
      k = k * ct;
      k = k % n;
    }

    pt = k + 96;
    m[i] = pt;
    i++;
  }

  m[i] = -1;
  cout << "\nEl mensaje desencriptado es\n";

  for (i = 0; m[i] != -1; i++)
    printf("%c", m[i]);
}
    
asked by Jose 25.11.2016 в 21:28
source

3 answers

3

With all due respect, your code is chaotic. An example:

int numeroint = 4;
int porcentajetotal = 100 / numeroint; // ¿Por qué no poner directamente 25?
porcentajeA = porcentajetotal;
porcentajeB = porcentajetotal;
porcentajeA = porcentajeB; // ¿Por qué esta asignación?

And another one:

cout <<"\nPorcentaje de realización del Hilo B : " <<porcentajeA<<"% \n"; // ¿No debería ser B?
porcentajeA =porcentajeA + porcentajeTempDos; // ¿No debería ser B?
cout<<"fin del hilo B\n";

If you have not received more answers at this point it is because your code is complicated to read and follow. It needs a deep refactoring to be minimally readable. I give you some tips:

Global variables

The first problem that your program has is the abusive use of global variables. The variables must have the shortest possible life ... and declaring by default the variables as global can give you many problems ... especially if you work with threads (basically because the same variable can be modified by two different threads if you do not realize) . The global variables should cease to exist in your program (at most it would leave mu , cv and ready .) Are you able to know what value is, for example, j in each moment? there are more elegant and secure ways to share information between threads.

Function prime ()

On the other hand, prime() should return a boolean, since it can only return two possible results: 1 (it's a prime) and 0 (it's not a prime):

bool prime(long int pr) {
  long int j = static_cast<long int>(sqrt(pr));
  for (long int i = 2; i <= j; i++) {
    if (pr % i == 0)
      return false;
  }
  return true;
}

This allows you to simplify the code and move from, for example, this:

flag = prime(i);
if (flag == 1 && i != p && i != q)

To this:

if (prime(i) && i != p && i != q)

Threads with parameters

The thread class allows you to send values to threads through parameters ... you can use this feature to share variables:

void ThreadB_Activity(int porcentaje);

std::thread ThreadB(ThreadB_Activity,porcentajeA);

You could even pass references to share values:

void ThreadB_Activity(int& porcentaje);

std::thread ThreadB(ThreadB_Activity,std::ref(porcentajeA));

Conversions

To make conversions it is preferable to use the C ++ ones. They are safer and easier to locate in code:

Change this:

srand((unsigned int) time((time_t *) NULL));

Because of this:

srand(static_cast<unsigned_int>(time(NULL)));    // C++99
srand(static_cast<unsigned_int>(time(nullptr))); // C++11 (Recomendado)

Data types

long int is equivalent to long , shorter and readable.

If a division involves, for example, a double with a int the result will always be double : double x = static_cast<double>(rand) / INT_MAX;

If the calculations are generally with strictly positive numbers, it would be better to use unsigned long or unsigned long long a long int .

For arrays it is preferable to use std::array<long,100> m to long m[100] . std::array has many features that a raw array does not and the performance penalty tends to zero.

Return values

If a function had to return two or more values you can use std::pair or std::tuple (the latter if you compile with C ++ 11 or later). It is always better than using global variables. You can store your individual elements in independent variables using the function std::tie . As always, this is preferable to using global variables:

std::pair<int,char> func()
{
  return std::make_pair(10,'f');
}

int main()
{
  int numero;
  char c;

  std::tie(numero,c) = func();
  std::cout << numero << ' ' << c << '\n';
}

Thread lock

And well, as regards the issue of the threads ... the waits you are commenting on are already being implemented:

Block until another thread notifies:

std::unique_lock<std::mutex> lk(mu);
cv.wait(lk, []{return ready;});

Notification of a thread:

std::lock_guard<std::mutex> lk(mu);
ready = true;
cv.notify_one(); // notificamos que el valor de 'ready' ha cambiado

By the way, the block could leave it like this:

std::unique_lock<std::mutex> lk(mu);
cv.wait(lk);

And then it would no longer be necessary to use ready . The thread would wait for someone to call cv.notify_one() or cv.notify_all() . In your case it does not make sense to use ready since whenever you call cv.notify_one() you are modifying true the value of ready . This block is designed for those cases in which the notification does not need to be paired with the change of the variable (for example if the value of ready depends on an external process).

If it does not work at any point in the code it is preferable to focus the question only at that point ... if what you expect is that someone debug the entire program for you perhaps you should consider offering a payment for these services.

    
answered by 28.11.2016 в 00:07
1

In the following code you have two threads working alternately, in that example protecting a shared resource. More examples and that you can find in my article on condition_variable

std::mutex alternateThreadsMutex;
std::condition_variable runThread1condition;
std::atomic<bool> runThread1 = false;
std::atomic<bool> runThread2 = false;
std::condition_variable runThread2condition;
std::vector<int> threadWork;

void thread1()
{
    while (true)
    {
        std::unique_lock<std::mutex> lock(alternateThreadsMutex);
        runThread1condition.wait(lock, []() { return runThread1.load(); });
        auto workSize = threadWork.size();
        if (workSize < 1000)
            threadWork.push_back(1);

        runThread1 = false;
        runThread2 = true;
        lock.unlock();

        runThread2condition.notify_one();
        if (++workSize >= 1000)
        {
            break;
        }
    }
}

void thread2()
{
    while (true)
    {
        std::unique_lock<std::mutex> lock(alternateThreadsMutex);
        runThread2condition.wait(lock, []() { return runThread2.load(); });
        auto workSize = threadWork.size();
        if (workSize < 1000)
            threadWork.push_back(1);

        runThread2 = false;
        runThread1 = true;
        lock.unlock();
        runThread1condition.notify_one();
        if (++workSize >= 1000)
        {
            break;
        }
    }
}


void alternateThreads()
{
    std::thread t1(thread1);
    std::thread t2(thread2);

    runThread2 = true;
    runThread2condition.notify_one();

    t1.join();
    t2.join();

    cout << threadWork.size() << el;
}
    
answered by 19.03.2018 в 18:11
0

From what you tell me, I can tell you that you use Sleep(); but in reality you would be pausing it for a while in milliseconds, now if you want to do it as if it were a boolean because you say you want to do it when an event happens what I see, then you should use the threads creator of the standard library of <windows.h>

Example:

#include <iostream>
#include <windows.h>

using namespace std;

HANDLE tha; // nuevo handle para el thread

DWORD WINAPI threada(LPVOID arg)
{
    cout << "Me ejecuto sin problemas!" << endl;
    SuspendThread(tha); // auto suspencion
    cout << "Continua la ejecucion de tha!" << endl;
    return 0;
}



int main()
{

    tha = CreateThread(NULL,0,threada,NULL,0,NULL);

    Sleep(10000); // thread principal main(); durmiendo por 10 segundos!

    ResumeThread(tha); // continua tha! - se levanta la suspensión


    system("pause");
    return 0;
}

P.S: Sleep(); is just an example, you can call the function ResumeThread(); before any event you want.

    
answered by 26.11.2016 в 03:16