In einem kürzlichen Interview wurde ich gebeten, einen threadsicheren generischen Stack auf C++ auf einem Linux-Rechner zu implementieren.
Ich kam schnell auf Folgendes (Es kann Kompilierungsfehler haben).
Ich kam durch. Der Interviewer mochte wahrscheinlich etwas in dieser Implementierung. Vielleicht der Entwurfsteil :)
Hier sind ein paar Probleme, die diese Implementierung haben kann: -
1. Falsche Implementierung, um Überlauf/Unterlauf anzuzeigen. Es gibt keine Überlaufbehandlung, da ich den STL-Vektor als zugrunde liegende Datenstruktur verwende. Sollte es eine solche Handhabung geben? Auch der Unterlauf (in Pop()) ergibt false als Rückgabewert. Sollte es durch Auslösen einer Ausnahme geschehen?
2. Implementierung der PopElem-Routine. Ist die folgende Implementierung korrekt?
3. Keine echte Verwendung des oberen Elements.
4. Bessere Zeit zwischen dem Start von Writer und Reader-Thread.Implementieren eines thread-sicheren, generischen Stacks in C++ unter Linux
Bitte machen Sie Kommentare/Vorschläge/Verbesserungen.
Danke.
// Implementierung eines Thread-sicheren generischen Stacks.
#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();
}
Warum Pop() nimmt einen Parameter? Soll pop das oberste Element des Stacks entfernen? –
@Appu Pop verwendet einen Parameter, mit dem Sie auf das Element verweisen können, das aus dem Stapel entfernt wurde. –