En una entrevista reciente, me pidieron que implementara una pila genérica segura (es decir, basada en una plantilla) en C++, en una máquina Linux.
Rápidamente se me ocurrió lo siguiente (Puede tener errores de compilación).
Terminé. Al entrevistador probablemente le gustó algo en esta implementación. Tal vez la parte de diseño :)
Aquí hay algunos problemas que puede tener esta implementación: -
1. Implementación incorrecta para indicar desbordamiento/subdesbordamiento. No hay manejo de desbordamiento ya que estoy usando el vector STL como la estructura de datos subyacente. ¿Debería haber tal manejo? Además, underflow (en Pop()) produce falso como valor de retorno. ¿Debería hacerse lanzando una excepción?
2. Implementación de la rutina PopElem. ¿La implementación a continuación es correcta?
3. No uso real del elemento superior.
4. Mejor sincronización entre el inicio del escritor y el hilo del lector.Implementación de una pila genérica segura para subprocesos en C++ en linux
Por favor, haga cualquier comentario/sugerencia/mejora.
Gracias.
// Implementando una pila genérica segura para hilos.
#include<pthread.h>
#include<iostream>
#include<vector>
using namespace std;
template<typename T>
class MyStack
{
public:
//interface
bool Push(T elem);
bool Pop(T& elem);
bool IsEmpty();
//constructor
MyStack() {
pthread_mutex_init(&lock);
top = 0;
}
//destructor
~MyStack() {
pthread_mutex_destroy(&lock);
}
private:
pthread_mutex_t lock;
int top;
vector<T> stack;
bool MyStack::Push(T elem);
bool MyStack::PopElem(T& elem);
}; //end of MyStack
template<typename T>
bool MyStack<T>::Push(T elem)
{
pthread_mutex_lock(&lock);
PushElem(elem);
pthread_mutex_unlock(&lock);
}
template<typename T>
bool MyStack<T>::Pop(T& elem)
{
pthread_mutex_lock(&lock);
PopElem(elem);
pthread_mutex_unlock(&lock);
}
template<typename T>
bool MyStack<T>::PushElem(T elem)
{
stack.push_back(elem);
top = stack.size();
}
template<typename T>
bool MyStack<T>::PopElem(T& elem)
{
if(this.IsEmpty())
{
return false;
}
elem = stack.back(); //tricky, returns a reference to the last element
stack.pop_back(); // is elem valid after this ??
top = stack.size();
return true;
}
template<typename T>
bool MyStack<T>::IsEmpty()
{
return stack.empty();
}
class MyStackTest
{
public:
void Initialize() {
pthread_init(&readerT);
pthread_init(&writerT);
}
void Run() {
pthread_create(writerT,0,writer,0);
pthread_create(readerT,0,reader,0);
pthread_join(&writerT);
pthread_join(&readerT);
}
private:
pthread_t readerT;
pthread_t writerT;
MyStack<int> stack;
void reader(void);
void writer(void);
};
void MyStackTest::writer() {
for(int i=0;i<20;i++) {
stack.Push(i);
cout<<"\n\t Pushed element: "<<i;
} //end for
}
void MyStackTest::reader() {
int elem;
while(stack.Pop(elem))
{
cout<<"\n\t Popped: "<<elem;
}
}
int main()
{
MyStackTest Test;
Test.Run();
}
¿Por qué Pop() está tomando un parámetro? ¿Debería eliminarse el elemento superior de la pila? –
@Appu Pop toma un parámetro para que pueda hacer referencia al elemento que se eliminó de la pila. –