Thread_specific_ptr en subprocesos múltiples en la biblioteca boost

       La mayoría de las funciones no son reentrantes. Esto significa que cuando un hilo ya ha llamado a una función, no es seguro volver a llamar a la misma función. Por ejemplo, std :: strtok no es reentrante porque usa variables estáticas para almacenar la cadena que se dividirá en símbolos.

Prototipo de función: char * strtok (char * s, const char * delim)

Función: descomponer una cadena en un conjunto de cadenas, s es la cadena a descomponer y delim es la cadena delimitada

Descripción: strtok () se usa para dividir la cadena en fragmentos, el parámetro s apunta a la cadena a ser separada, el parámetro delim es la cadena delimitada, cuando strtok () encuentra el parámetro delim en la cadena del parámetro s Al separar el carácter, el carácter se cambiará al carácter '\ 0'. En la primera llamada, se debe dar strtok () a la cadena del parámetro, y las llamadas posteriores establecerán el parámetro en NULL. Cada llamada se realiza correctamente Devuelve el puntero del fragmento separado.


#include <iostream>   
#include <cstring>   
using namespace std;   
int main()   
{   
 char sentence[]="This is a sentence with 7 tokens";  
  
 cout<<"The string to be tokenized is:\n"
  <<sentence<<"\n\nThe tokens are:\n\n"; 
   
 char *tokenPtr=strtok(sentence," "); 
   
 while(tokenPtr!=NULL) {   
  cout<<tokenPtr<<'\n';   
  tokenPtr=strtok(NULL," ");   
 } 
   
 cout<<"After strtok, sentence = "<<sentence<<endl;   
 return 0;   

/ * Deben establecerse dos parámetros para la primera llamada de la función. El resultado de la primera división, devuelve la cadena antes del primer ',' en la cadena, que es la primera vez que el programa anterior genera abc.   
 * La función strtok (NULL, ",") se llama por segunda vez y el primer parámetro se establece en NULL. El resultado se devuelve a la cadena siguiendo la base de segmentación, que es la segunda salida d.   
 * strtok es una función insegura para subprocesos, porque usa espacio asignado estáticamente para almacenar la posición de la cadena dividida   
 * La función segura para subprocesos se llama strtok_r, ca   
 * Cuando use strtok para determinar ip o mac, asegúrese de usar otros primero El método para juzgar el número de '.' O ':',
 * Porque usando strtok truncado, como: "192..168.0 ... 8 ..." esta cadena, strtok solo interceptará cuatro veces, el medio. .. No importa cuántos serán tratados como clave
 * /      

El contenido anterior se cita en: https://blog.csdn.net/luciazzzz/article/details/38538033

       Una función no reentrante guarda variables estáticas o devuelve un puntero a datos estáticos a través de llamadas sucesivas Hay dos formas de convertir una función no reutilizable en una función reutilizable.

       Método 1: cambie la interfaz y reemplace los datos estáticos originales con punteros o referencias. Por ejemplo, POSIX define strok_r, una variable reentrante en std :: strtok, que usa un parámetro char ** adicional para reemplazar los datos estáticos. Este método es simple y proporciona los mejores resultados posibles. Pero esto debe cambiar la interfaz pública, lo que significa que se debe cambiar el código.

        Método 2: no cambie la interfaz pública, use almacenamiento local de subprocesos en lugar de datos estáticos (a veces llamado almacenamiento específico de subprocesos).

       La biblioteca de subprocesos Boost proporciona un puntero inteligente boost :: thread_specific_ptr para acceder al subproceso de almacenamiento local. thread_specific_ptr es un contenedor para el almacenamiento local de subprocesos, que se puede usar para envolver variables globales independientes de subprocesos. Cuando cada subproceso usa la instancia de este puntero inteligente por primera vez, su valor inicial es NULL (por lo que primero debe verificar si su valor está vacío). Antes de que cada subproceso lo use, se debe entregar un nuevo objeto al global Thread_specific_ptr es administrado. Cuando el hilo sale, la biblioteca de hilos de Boost garantiza que los datos guardados en el hilo de almacenamiento local se borrarán después de que finalice el hilo. De esta manera, cada hilo puede acceder de forma independiente a la versión de almacenamiento local de esta variable global. no causa competencia de recursos debido al acceso al mismo objeto global y causa degradación del rendimiento. Cuando finaliza el hilo, este recurso se liberará automáticamente.

Se puede aplicar en los dos escenarios siguientes:

       1. Adapte una interfaz de biblioteca diseñada originalmente para un solo hilo, como la función strtok en libc. Este tipo de biblioteca generalmente usa implícitamente una variable global, y thread_specific_ptr puede usarse para controlar la variable global de modo que pueda usarse para múltiples subprocesos.
       2. Se utilizan una serie de métodos / funciones en el hilo, necesitan una variable global lógica para compartir datos, pero de hecho esta variable es independiente del hilo.

thread_specific_ptr representa el almacenamiento local de una variable global, y cada hilo puede acceder de forma independiente a la copia local de esta variable global a través de él, lo que tiene el efecto de no dañar el río.

Un ejemplo simple del uso de boost :: thread_specific_ptr.

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/tss.hpp>
#include <iostream>
 
boost::mutex io_mutex;
boost::thread_specific_ptr<int> ptr;
 
struct count
{
        count(int id) : id(id) { }
        
        void operator()()
        {
                if (ptr.get() == 0)
                ptr.reset(new int(0));
                
                for (int i = 0; i < 10; ++i)
                {
                        (*ptr)++;
                        boost::mutex::scoped_lock
                        lock(io_mutex);
                        std::cout << id << ": "
                        << *ptr << std::endl;
                }
        }
        
        int id;
};
 
int main(int argc, char* argv[])
{
        boost::thread thrd1(count(1));
        boost::thread thrd2(count(2));
        thrd1.join();
        thrd2.join();
        return 0;
}

Se crean dos subprocesos para inicializar el subproceso de almacenamiento local, y hay 10 ciclos. Cada vez que el valor apuntado por el puntero inteligente aumenta y se envía a std :: cout (dado que std :: cout es un recurso compartido, por lo que la sincronización a través mutex). El hilo principal espera el final de estos dos hilos y luego sale. A partir de la salida de este ejemplo, se puede ver claramente que cada hilo procesa su propia instancia de datos, aunque todos usan el mismo boost :: thread_specific_ptr.

referencia:

https://blog.csdn.net/liujiayu2/article/details/50587084

https://blog.csdn.net/flyingleo1981/article/details/47083737

Supongo que te gusta

Origin blog.csdn.net/sunlin972913894/article/details/103647149
Recomendado
Clasificación