I would like to have a C++11 RAII component to count how many resources of a certain type are present in a multithreaded environment. I wrote the following:
#include <atomic>
#include <iostream>
using namespace std;
class AtomicCounter
{
public:
AtomicCounter(std::atomic< int > &atomic) : atomic(atomic) {
int value = ++this->atomic;
cerr << "incremented to " << value << endl;
}
~AtomicCounter() {
int value = --this->atomic;
cerr << "decremented to " << value << endl;
}
private:
std::atomic< int > &atomic;
};
int main() {
atomic< int > var;
var = 0;
AtomicCounter a1(var);
{
AtomicCounter a2(var);
cerr << "Hello!" << endl;
AtomicCounter a3(var);
}
cerr << "Good bye!" << endl;
return 0;
}
The idea is that I create an AtomicCounter object in each resource (for example, the main thread function) and this keeps the associated atomic variable updated.
Is this component correct, even when used in a multithreaded environment? Is there a standard component that already does this?
Related
I'm new to google test and currently I'm writing a test for my OOP program, my OOP program is like this:
#include <iostream>
#include <gtest/gtest.h>
using namespace std;
typedef unsigned int NUM;
class Employee
{
protected:
NUM MaSoThue;
private:
NUM Luong;
NUM CMND;
NUM a;
NUM b;
public:
Employee()
{
MaSoThue = 0;
Luong = 0;
CMND = 0;
}
Employee(NUM mst, NUM luong, NUM cmnd)
{
MaSoThue = mst;
Luong = luong;
CMND = cmnd;
}
//get
int getMaSoThue() const { return MaSoThue; }
int getLuong() const { return Luong; }
int getCMND() const {return CMND;}
//set
void setMaSoThue(NUM mst) {if (MaSoThue==0) MaSoThue = mst;}
void setLuong(NUM luong) {Luong = luong;}
void setCMND(NUM cmnd) {if (CMND==0) CMND = cmnd;}
};
int main()
{
// Objects
Employee PhucTri(111,222,333);
Employee MinhDang;
MinhDang.setMaSoThue(1234);
MinhDang.setLuong(2);
MinhDang.setCMND(8888);
//PhucTri
cout <<"MST cua Phuc Tri: "<< PhucTri.getMaSoThue()<<"\n";
cout << "Luong cua Phuc Tri: " << PhucTri.getLuong() << "\n";
cout << "CMND cua Phuc Tri: " << PhucTri.getCMND() << "\n\n";
//MinhDang
cout << "MST cua Minh Dang: " << MinhDang.getMaSoThue() << "\n";
cout << "Luong cua Minh Dang: " << MinhDang.getLuong() << "\n";
cout << "CMND cua Minh Dang: " << MinhDang.getCMND() << "\n";
}
I created a new file, which is below:
#include <gtest/gtest.h>
#include "FileCode.cc"
int main(){}
TEST(No1, PhucTri){
EXPECT_EQ(PhucTri.getMaSoThue(),111);
}
The compiler says that the object "PhucTri" isn't declared in this scope, but I did create it in my first file, is there any way I can get it right on the object ?
In general, Try to not include .cpp files, declare your class and its methods inside a .h file, define methods in .cpp and then create a test file that includes your header.
You have two options here, either define a test class that has an instance of your class follows instructions here.
Or do something like this :
#include <gtest/gtest.h>
#include "FileCode.h"
TEST(No1, PhucTri)
{
Employee PhucTri(111,222,333);
// initialize your data
// ......
EXPECT_EQ(PhucTri.getMaSoThue(),111);
}
I included the logger from boost. I'm pretty pleased how it works. Just for simplicity and the reason I don't want to use makros to often in my code, I wrap it in a class.
I now wonder if I could use the streaming operator << to write on a member function.
code
class LogWrapper{
...
//debug function
//info function
...
}
void main() {
LogWrapper log;
log.debug() << "some debug msg"; // does this exist?
log.info() << "some info msg";
}
output
[some_timestamp][debug] some debug msg
[some_timestamp][info] some info msg
Is this possible in a good practice, or is it entirely bad style?
It can be done easily like this:
#include <iostream>
class A {
public:
std::ostream &debug() const {
std::cerr << "[timestamp]" << "[DEBUG]";
return std::cerr;
}
};
int main()
{
A a;
a.debug() << "Test";
}
But the important question here is: Should we implement it in this way? In my opinion, NO!
Because you are thinking that the User of the class will print the logs like this:
int main()
{
A a;
a.debug() << "Test" << std::endl;
a.debug() << "Test2" << std::endl;
}
Output:
[timestamp][DEBUG]Test
[timestamp][DEBUG]Test2
But what if User chooses this way:
int main()
{
A a;
auto &out = a.debug();
out << "Test" << std::endl;
out << "Test2" << std::endl;
}
Output:
[timestamp][DEBUG]Test
Test2
I would highly recommend not to return stream object. You should use member functions for this purpose.
#include <iostream>
class A {
public:
static void debug(const std::string &log) {
std::cerr << "[timestamp]" << "[DEBUG]" << log << std::endl;
}
};
int main()
{
A::debug("Test 1");
A::debug("Test 2");
}
Output:
[timestamp][DEBUG]Test 1
[timestamp][DEBUG]Test 2
I am learning about functions and classes, and wrote my own code. I used the constructor to just initialize the variables. I have a function that is supposed to get the info I initialized with the constructor and allow me to display it. However, it doesn't want to work. I am not really sure what I am doing wrong. My error code says that I have unresolved externals because of my "void" function. I thought my function was not returning anything but rather just displaying the input it got from the initialization of the constructor.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class Berries {
string Nameofberries;
int Price;
public:
Berries (string N,int B)
{
Nameofberries = N;
Price = B;
}
void GetBerryInfo(const Berries& B)
{
cout << B.Nameofberries << endl;
cout << B.Price << endl;
}
};
void GetBerryInfo (const Berries& B);
int main ()
{
Berries Berryinfo1( "Raspberries", 7);
cout << GetBerryInfo;
system("pause");
return 0;
}
There are several mistakes.
void GetBerryInfo(const Berries& B)
{
cout << B.Nameofberries << endl;
cout << B.Price << endl;
}
should be
void GetBerryInfo()
{
cout << Nameofberries << endl;
cout << Price << endl;
}
==================================================================
void GetBerryInfo (const Berries& B);
should be removed.
==================================================================
cout << GetBerryInfo;
should be
Berryinfo1.GetBerryInfo();
==================================================================
All computer langauges are fussy, you have to get the details right, as well as understand the concepts.
This will do what you wanted:
# include <iostream>
# include <iomanip>
# include <string>
using namespace std;
class Berries {
string Nameofberries;
int Price;
public:
Berries (string N,int B)
{
Nameofberries = N;
Price = B;
}
void GetBerryInfo()
{
cout << Nameofberries << endl;
cout << Price << endl;
}
};
int main ()
{
Berries Berryinfo1( "Raspberries", 7);
Berryinfo1.GetBerryInfo();
system("pause");
return 0;
}
A couple of points on your mistakes:
GetBerryInfo() was declared inside the class. You don't need to re-declare it in the global scope. That 2nd declaration should be removed.
To be invoked, functions (like GetBerryInfo) must have () at the end of them like so: GetBerryInfo().
There is no point for GetBerryInfo() to take Berries as a paremeter. It is a member function that is part of the class Berries. It has access to all data members of a Berries instance already.
You don't need to use cout here: cout << GetBerryInfo; because the function body already sends the data members to cout. This function returns void so it doesn't make sense to send this to cout anyway.
I'm implementing my own hash table and I am running into the following problem: when I insert my node(s) into the table, they are not printed out when I loop through the array. I am using an array of arrays as the underlying data structure and the logic is as follows:
I pass my node to an insert function. This function, based on the
type of data in my node, calls the appropriate hash function provided
by the C++ STL.
Then, I mod the hash value returned by the size of
my hash table and use that to determine which array to place the
node.
I also have an array of arrays of booleans (the same size as my
hash table) that I use to check whether a specific spot in my hash
table already has data in it.
If it does, I simply keep looping till
an empty spot is found.
Like I said before, the problem is that the data is inputed correctly into the array (I've checked that with print statements), but when I print the array, nothing is outputted. I have also checked if my object is being constructed correctly (again, with print statements), but everything is looking fine. I've included the full code below. Any help would be greatly appreciated!
///////START OF NODE.H///////////
#ifndef NODE_H
#define NODE_H
#include <iostream>
template <typename T>
class HashTable;
template <typename T>
class Node
{
friend class HashTable<T>;
private:
T data;
public:
Node(T Data): data(Data)
{
std::cout << "In the node constructor" << std::endl;
}
Node()
{
decltype(data) {};
}
T getData() const
{
return data;
}
};
#endif
//////////////////////END OF NODE.H////////////////////
/////START OF HASHTABLE.H///////
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include "Node.h"
#include <iostream>
#include <array>
#include <functional>
#include <typeinfo>
#include <string>
const int TABLE_SIZE=5;
template <typename T>
class HashTable
{
private:
std::array<std::array<Node<T>, TABLE_SIZE>, TABLE_SIZE> hashTable;
std::array<std::array<bool, TABLE_SIZE>, TABLE_SIZE> spots;
public:
HashTable()
{
for(int index=0;index<spots.size();++index)
{
for(int position=0;position<spots.at(index).size();++position)
{
spots.at(index).at(position)=false;
}
}
}
int hashFunction(Node<T> Node)
{
auto key=Node.getData();
std::hash<decltype(Node.getData())> hash_function {};
int hash=hash_function(key);
if(hash < 0)
{
hash*=-1;
}
//std::cout << "The hash value return by the STL hash function for the key " << key << " is " << hash << std::endl;
if(hash > TABLE_SIZE)
{
hash%=TABLE_SIZE;
}
std::cout << "The hash value for the key " << key << " is " << hash << std::endl;
return hash;
}
void insert(Node<T> Node)
{
int hashValue=hashFunction(Node);
auto location=hashTable.at(hashValue);
std::cout << "Going to insert " << Node.getData() << std::endl;
for(int index=0;index<location.size();++index)
{
if(spots.at(hashValue).at(index)==false)
{
std::cout << "Found a spot that is not taken!" << std::endl;
std::cout << "The size of the data at the spot in the array before we insert is: " << location.at(index).getData().size() << std::endl;
location.at(index)=Node;
std::cout << "The size of the data at the spot in the array after we insert is: " << location.at(index).getData().size() << std::endl;
std::cout << "The data that is in the spot in the array: " << location.at(index).getData() << std::endl;
std::cout << std::endl;
spots.at(hashValue).at(index)=true;
break;
}
}
}
bool contains(Node<T> Node)
{
int hashValue=hashFunction(Node);
auto location=hashTable.at(hashValue);
auto result=find_if(begin(location), end(location), [Node] (const auto & element) {return element.getData()==Node.getData();});
if(result!=end(location))
{
return true;
}
return false;
}
int getSize() const
{
int size {};
for(int index=0;index<hashTable.size();++index)
{
size+=hashTable.at(index).size();
}
return size;
}
void print()
{
std::cout << "In the print function" << std::endl;
for(int index=0;index<hashTable.size();++index)
{
//std::cout << hashTable.at(index).size() << std::endl;
for(int position=0;position<hashTable.at(index).size();++position)
{
std::cout << hashTable.at(index).at(position).getData().size() << std::endl;
}
}
/*
for(int index=0;index<spots.size();++index)
{
for(int position=0;position<spots.at(index).size();++position)
{
if(spots.at(index).at(position)==true)
{
std::cout << "There should be some data here" << std::endl;
}
}
}
*/
}
};
#endif
////////////END OF HASHTABLE.H//////////
////////////START OF MAIN.CPP///////////
#include "HashTable.h"
#include <cstdlib>
#include <random>
#include <algorithm>
using namespace std;
int main()
{
HashTable<string> hash_table;
hash_table.insert(Node<string>("Java"));
hash_table.insert(Node<string>("C++"));
hash_table.insert(Node<string>("C#"));
hash_table.insert(Node<string>("Latex"));
hash_table.insert(Node<string>("Python"));
}
/////////////END OF MAIN.CPP/////////////
One error is in your insert(Node<T> Node) function on these line:
auto location=hashTable.at(hashValue);
//...
location.at(index) = Node;
The location should be a reference not a copy. What is happening is that you're making changes to a local location, and not the actual location that the hash table uses. Thus none of your changes "stick".
The line above should be this:
auto& location=hashTable.at(hashValue); // <-- note that auto is a reference
//...
location.at(index) = Node;
Now you are assigning the returned reference to a reference.
Also, I highly recommend you use a debugger, as this error could have been easily diagnosed if you stepped through your code to see what was being done.
in HashTable::insert this line:
auto location = hashTable.at(hashValue);
makes a copy of a Node. You then operate on and store in the copy, not the node in hashTable. Taking a reference to the node
auto & location = hashTable.at(hashValue);
should fix it.
When i am passing an object to a function, I am getting undesired results. It seems to happen when I pass a Character through a Mage's action() function.
Here are some snippits of my code:
character.h
class Character {
public:
Character();
int getMaxLives() const;
int getMaxCraft() const;
protected:
maxLives;
maxCraft;
};
character.cpp
#include "character.h"
Character::Character () {
maxLives = 5;
MaxCraft = 10;
}
int Character::getMaxLives() const {
return maxLives;
}
int Character::getMaxCraft() const {
return maxCraft;
}
mage.h
#include "character.h"
class Mage {
public:
Mage();
void action(Character c1);
};
mage.cpp
#include "mage.h"
Mage::Mage () { ... }
void Mage::action(Character c1) {
cout << "Max Craft: " << c1.getMaxCraft() << endl;
cout << "Max Lives: " << c1.getMaxLives() << endl;
}
driver.cpp
int main () {
Character c1;
Mage m1;
m1.action(c1);
My ouput gives me the following:
Max Craft: 728798402 (The number varies)
Max Lives: 5
However, if in my diver, i do:
cout << "Max Craft: " << c1.getMaxCraft() << endl;
cout << "Max Lives: " << c1.getMaxLives() << endl;
I get:
Max Craft: 10
Max Lives: 5
Any ideas?
Looks like you meant for MaxCraft = 10; (in your default constructor) to actually be maxCraft = 10;. As #chris says in the comments, it appears that you're using some (evil, evil) C++ extension that allows implicitly-typed variables, so the MaxCraft = 10; line is simply defining a new variable named MaxCraft.