I am using QT 4.8 and I notice that it has a QHash class which can be used as follows:
QHash<QString, int> hash;
hash["one"] = 1;
hash["three"] = 3;
hash["seven"] = 7;
hash.insert("twelve", 12);
If there is a hash collision, will it be handled correctly?
Yes, collisions will be handled. QHash is a standard implementation of the classic hash-table based container and wouldn't be very reliable if it didn't handle collisions correctly. Typically a hash-table based container will map keys not to a single entry in the list but to a "bucket" which may contain more than one entry where different keys map to the same hash value.
When fetching values, the hash value for the key leads to the correct bucket then the container will iterate through the entries in the bucket until it finds a match for the particular key you are looking for.
Although I could not find a specific reference in the documentation to the "correctness" of Qt's implementation, this quote eludes to it. I can't imagine it being otherwise.
QHash's internal hash table grows by powers of two, and each time it
grows, the items are relocated in a new bucket, computed as qHash(key)
% QHash::capacity() (the number of buckets).
A simple test will increase our confidence:
BadHashOjbect.h
#ifndef BADHASHOBJECT_H
#define BADHASHOBJECT_H
class BadHashObject
{
public:
BadHashObject(const int value): value(value){}
int getValue() const
{
return value;
}
private:
int value;
};
bool operator==(const BadHashObject &b1, const BadHashObject &b2)
{
return b1.getValue() == b2.getValue();
}
uint qHash(const BadHashObject &/*key*/)
{
return 1;
}
#endif // BADHASHOBJECT_H
main.cpp
#include <iostream>
#include <QHash>
#include "BadHashObject.h"
using namespace std;
int main(int , char **)
{
cout << "Hash of BadHashObject(10) is: " << qHash(BadHashObject(10)) << endl;
cout << "Hash of BadHashObject(100) is: " << qHash(BadHashObject(100)) << endl;
cout << "Adding BadHashObject(10), value10 and BadHashObject(100), value100" << endl;
QHash<BadHashObject, QString> hashMap;
hashMap.insert(BadHashObject(10), QString("value10"));
hashMap.insert(BadHashObject(100), QString("value100"));
cout << "Size of hashMap: " << hashMap.size() << endl;
cout << "Value stored with key 10: " << hashMap.value(BadHashObject(10)).toStdString() << endl;
cout << "Value stored with key 100: " << hashMap.value(BadHashObject(100)).toStdString() << endl;
}
The BadHashObject class stores an int and its hash function will always return 1 so all objects added to a QHash using this type as a key will result in a collision. The output from our test program shows that the collision is handled properly.
Hash of BadHashObject(10) is: 1
Hash of BadHashObject(100) is: 1
Adding BadHashObject(10), value10 and BadHashObject(100), value100
Size of hashMap: 2
Value stored with key 10: value10
Value stored with key 100: value100
Related
I‘ve been trying to understand smart pointers, and as I understood, smart pointer will destroy themselves once they are not reachable through the code.
For this reason I was trying to implement a demonstration for this behavior:
#include<iostream>
#include<memory>
using namespace std;
void shared(){
cout<<"Shared Pointer:"<<endl;
shared_ptr<int> number = make_shared<int>(50);
cout<<*number<<endl;
cout<<number<<endl;
}
int main(){
int address;
shared();
cout<<"please enter the targeted address:"<<endl;
cin>>address;
int *pointer = (int *) address;
cout<<"we found this number: "<<*pointer<<endl;
}
output:
Shared Pointer:
50
0xf28c30
please enter the targeted address:
15895600 // I just converted the hexdecimal above to decimal number.
we found this number: 50
So I‘m able to retrieve the value 50 from outside the function shared(), by manually entering its address in the console.
Isn‘t supposed to be null or random number? If this is normal then how smartpointers are made to avoid memory leaks!?
P.S: doing the same test using a normal pointer will produce the same results unless we add delete pointer; (which is the expected behavior)
I appreciate any idea about this specific behavior.
To make sure that the memory was deleted it is better to test the smart pointers with a class
class Greeting {
public:
Greeting()
{
std::cout << "Hello" << std::endl;
}
~Greeting()
{
std::cout << "Bye" << std::endl;
}
};
void shared() {
shared_ptr<Greeting> var = make_shared<Greeting>();
}
int main() {
std::cout << "Start" << std::endl;
shared();
std::cout << "End" << std::endl;
}
You will get the following output:
Start //Start of the main
Hello // When creating the object (the resource)
Bye // **When destructing the object (the resource)**
End //End the main
I'm not very good at character devices, so I need your help. A have a char device(let's call it /dev/my_light) which is a light sensor. I have to read the data from this file and transform it to the brightness value and then pass it to the brightness manager that changes the brightness of my screen. The problem is that when I read the value for some period of time I get old values from the file.I assume there is a buffer(again not sure how character devices exactly work). Whereas when I use cat /dev/my_light I see new data! Is it possible to get rid off the buffer and read new values that were written to the file just right now. Here is my code in Qt:
void MySensor::updateMySensor()
{
Packet packet;
packet.startByte = 0;
packet.mantissa = 0;
packet.exp = 0;
d->device = ::open(d->path.toStdString().c_str(), O_RDONLY);
if (d->device == -1)
{
qDebug() << Q_FUNC_INFO << "can't open the sensor";
return;
}
ssize_t size = ::read(d->device, &packet, sizeof(packet));
close(d->device);
if (size == -1)
{
qDebug() << errno;
return;
}
packet.exp &= 0x0F;
float illumination = pow(2, packet.exp) * packet.mantissa * 0.045;
if(d->singleShot) emit lightSensorIsRunning(true);
emit illuminationRead(illumination);
}
The mySensor function is called every second. I tried to call it each 200 msec but it didn't help. The value of illumination stays old for about 7 seconds(!) whereas the value that I get from cat is new just immediately.
Thank you in advance!
I can't test with your specific device, however, I'm using the keyboard as a read only device.
The program attempts to connect to keyboard and read all keys pressed inside and outside the window. It's a broad solution you'll have to adapt to meet your demands.
Note that I'm opening the file with O_RDONLY | O_NONBLOCK which means open in read only mode and no wait for the event be triggered(some notifier needed to know when data is ready!) respectively.
You'll need super user privilege to run this example!
#include <QtCore>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const char *device_name = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
int descriptor = open(device_name, O_RDONLY | O_NONBLOCK);
if (descriptor < 0)
{
qDebug() << "Error" << strerror(errno);
return a.exec();
}
QFile device;
if (!device.open(descriptor, QFile::ReadOnly))
{
qDebug() << "Error" << qPrintable(device.errorString());
return a.exec();
}
QSocketNotifier notifier(device.handle(), QSocketNotifier::Read);
QObject::connect(¬ifier, &QSocketNotifier::activated, ¬ifier, [&](int socket){
Q_UNUSED(socket)
struct input_event ev;
QByteArray data = device.readAll();
qDebug() << "Event caught:"
<< "\n\nDATA SIZE" << data.size()
<< "\nSTRUCT COUNT" << data.size() / int(sizeof(input_event))
<< "\nSTRUCT SIZE" << sizeof(input_event);
qDebug() << ""; //New line
while (data.size() >= int(sizeof(input_event)))
{
memcpy(&ev, data.data(), sizeof(input_event));
data.remove(0, int(sizeof(input_event)));
qDebug() << "TYPE" << ev.type << "CODE" << ev.code << "VALUE" << ev.value << "TIME" << ev.time.tv_sec;
}
qDebug() << ""; //New line
});
return a.exec();
}
I've read the basics of move semantics and I did a couple of tests.
Case #1:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string st = "hello";
vector<string> vec;
vec.push_back(st);
cout << st;
cin.get();
}
In this case, the program will not print anything because "hello" has been moved to vector[0].
Case #2:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int num=5;
vector<int> vec;
vec.push_back(num);
cout << num;
cin.get();
}
Why does the program print "5"? I thought num would be 0 or something undefined.
Case #1 should print "hello". If not then your compiler has bug and you should upgrade to a newer version or complain to who ever wrote it.
Case #2 correctly prints "5".
However, if you changed line 10 in case 2 from:
vec.push_back(st);
to:
vec.push_back(std::move(st));
you will get what you expected, a print to console of "" because vector "stole" the value in st.
int is a fundamental type in c++ and trying to "steal" from an int variable doesn't realy work since it does't own any resource.
std::string is a resource owner. It "owns" a char array (this isn't always true, but for simplicity we will pretend it is).
So when we pass std::move(st) to push_back we are calling the T&& overload of push_back which does the "stealing" by calling the move constructor of std::string which releases st's handle and gives it to the newly created std::string inside vec.
But if we called push_back like this: vec.push_back(st); this will not "steal" any thing. Instead, it will call the const T& overload of push_back which just does a simple copy by calling the normal copy constructor of std::string such that we will have st set to "hello" and vec[0] set with its own version of "hello".
Try this code below to see how all this works out:
#include <iostream>
#include <vector>
using namespace std;
struct Foo
{
Foo() // default constructor
{
cout << "Foo()" << endl;
}
Foo(const Foo&) // copy constructor
{
cout << "Foo(const Foo&)" << endl;
}
Foo(Foo&&) // move constructor
{
cout << "Foo(Foo&&)" << endl;
}
Foo& operator=(const Foo&) // copy assignment operator
{
cout << "operator=(const Foo&)" << endl;
return *this;
}
Foo& operator=(Foo&&) // move assignment operator
{
cout << "operator=(Foo&&)" << endl;
return *this;
}
~Foo()
{
cout << "~Foo()" << endl;
}
};
int main()
{
Foo f; // print: Foo();
vector<Foo> vec;
vec.push_back(f); // print: Foo(const Foo&)
vec.push_back(std::move(f)); // print: Foo(Foo&&)
Foo f2; // print: Foo()
f2 = f; // print: operator=(const Foo&)
f2 = std::move(f); // print: operator=(Foo&&)
cin.get();
}
In an MPI application I have a distributed array of floats and two "parallel" arrays of integers: for each float value there are two associated integers that describe the corresponding value. For the sake of cache-efficiency I want to treat them as three different arrays, i.e. as a structure of arrays, rather than an array of structures.
Now, I have to gather all these values into the first node. I can do this in just one communication instruction, by defining an MPI type, corresponding to a structure, with one float and two integers. But this would force me to use the array of structures pattern instead of the structure of arrays one.
So, I can choose between:
Performing three different communications, one for each array and keep the efficient structure of arrays arrangement
Defining an MPI type, perform a single communication, and deal with the resulting array of structures by adjusting my algorithm or rearranging the data
Do you know a third option that would allow me do have the best of both worlds, i.e. having a single communication and keeping the cache-efficient configuration?
You take take a look at Packing and Unpacking.
http://www.mpi-forum.org/docs/mpi-11-html/node62.html
However, I think if you want to pass a same "structure" often you should define you own MPI derivate type.
E.g. by using the *array_of_blocklength* parameter of MPI_Type_create_struct
// #file mpi_compound.cpp
#include <iterator>
#include <cstdlib> // for rng
#include <ctime> // for rng inits
#include <iostream>
#include <algorithm>
#include <mpi.h>
const std::size_t N = 10;
struct Asset {
float f[N];
int m[N], n[N];
void randomize() {
srand(time(NULL));
srand48(time(NULL));
std::generate(&f[0], &f[0] + N, drand48);
std::generate(&n[0], &n[0] + N, rand);
std::generate(&m[0], &m[0] + N, rand);
}
};
int main(int argc, char* argv[]) {
MPI_Init(&argc,&argv);
int rank,comm_size;
MPI_Status stat;
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&comm_size);
Asset a;
MPI_Datatype types[3] = { MPI_FLOAT, MPI_INT, MPI_INT };
int bls[3] = { N, N, N };
MPI_Aint disps[3];
disps[0] = 0;
disps[1] = int(&(a.m[0]) - (int*)&a)*sizeof(int);
disps[2] = int(&(a.n[0]) - (int*)&a)*sizeof(int);
MPI_Datatype MPI_USER_ASSET;
MPI_Type_create_struct(3, bls, disps, types, &MPI_USER_ASSET);
MPI_Type_commit(&MPI_USER_ASSET);
if(rank==0) {
a.randomize();
std::copy(&a.f[0], &a.f[0] + N, std::ostream_iterator<float>(std::cout, " "));
std::cout << std::endl;
std::copy(&a.m[0], &a.m[0] + N, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
std::copy(&a.n[0], &a.n[0] + N, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
MPI_Send(&a.f[0],1,MPI_USER_ASSET,1,0,MPI_COMM_WORLD);
} else {
MPI_Recv(&a.f[0],1,MPI_USER_ASSET,0,0,MPI_COMM_WORLD, &stat);
std::cout << "\t=> ";
std::copy(&a.f[0], &a.f[0] + N, std::ostream_iterator<float>(std::cout, " "));
std::cout << std::endl << "\t=> ";
std::copy(&a.m[0], &a.m[0] + N, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl << "\t=> ";
std::copy(&a.n[0], &a.n[0] + N, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
MPI_Type_free(&MPI_USER_ASSET);
MPI_Finalize();
return 0;
}
worked with
mpirun -n 2 ./mpi_compound
with mpich2 v1.5 (HYDRA) on x86_86 linux and g++ 4.4.5-8 - based mpic++
In SQLite if I prepare a SELECT statement and begin stepping through it, then before the last row of the results is reached I execute another statement that has an effect on the SELECT statement that I am stepping through, what is the expected result?
I can't find anything in the SQLite documentation about what is supposed to happen but it seems like an extremely common case when programming in a multi-threaded environment.
Below is a c++ file that can be compiled and run on Windows to demonstrate the situation.
#include "stdafx.h"
#include "sqlite3.h"
#include <Windows.h>
#include <iostream>
#include <Knownfolders.h>
#include <Shlobj.h>
#include <wchar.h>
#include <comdef.h>
using namespace std;
int exec_sql(sqlite3 *db, const char* sql)
{
char *errmsg;
int result = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
if (result != SQLITE_OK) {
cout << errmsg << endl;
return -1;
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
cout << "Running jsqltst with SQLite version: ";
cout << sqlite3_libversion();
cout << endl;
PWSTR userhome;
if (!SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Profile, NULL, NULL, &userhome))) {
cout << "Failed getting user home dir\n";
return -1;
}
wcout << "User home: " << userhome << endl;
wchar_t *ws1 = userhome, *ws2 = L"\\test.sqlite";
wstring dbpath_str(ws1);
dbpath_str += wstring(ws2);
_bstr_t dbpath(dbpath_str.c_str());
cout << "DB path: " << dbpath << endl;
sqlite3 *db;
int result = sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
if (result != SQLITE_OK) {
cout << sqlite3_errmsg(db) << endl;
return -1;
}
const char * create_stmt = "CREATE TABLE IF NOT EXISTS atable (id INTEGER PRIMARY KEY, name TEXT, number INTEGER);";
if (exec_sql(db, create_stmt) != 0) {
return -1;
}
const char * delete_stmt = "DELETE FROM atable;";
if (exec_sql(db, delete_stmt) != 0) {
return -1;
}
const char * insert_stmt = "INSERT INTO atable (name,number) VALUES ('Beta',77),('Alpha',99);";
if (exec_sql(db, insert_stmt) != 0) {
return -1;
}
sqlite3_stmt* select_ss;
const char * select_stmt = "SELECT * FROM atable;";
result = sqlite3_prepare_v2(db, select_stmt, -1, &select_ss, NULL);
if (result != SQLITE_OK) {
cout << sqlite3_errmsg(db) << endl;
return -1;
}
int i = 0;
boolean gotrow;
do {
result = sqlite3_step(select_ss);
gotrow = result == SQLITE_ROW;
if (gotrow) {
i++;
cout << "I got a row!" << endl;
if (i == 1) {
if (exec_sql(db, insert_stmt) != 0) {
return -1;
}
}
}
} while (gotrow);
cout << "Last result: " << result << ", errstr: " << sqlite3_errstr(result) << endl;
result = sqlite3_finalize(select_ss);
if (result != SQLITE_OK) {
cout << sqlite3_errmsg(db) << endl;
return -1;
}
return 0;
}
SQLite's behaviour for concurrent statements in the same transaction is neither documented nor defined.
As you have seen, newly inserted records might be seen when a SELECT's cursor has not yet reached that part of the table.
However, if SQLite needed to create a temporary result table for sorting or grouping, later changes in the table will not appear in that result.
Whether you have a temporary table or not might depend on decisions made by the query optimizer, so this is often not predictable.
If multiple threads access the same connection, SQLite will lock the DB around each sqlite3_step call.
This prevent data corruption, but you will still have the problem that automatic transaction end when their last active statement ends, and that explicit transaction will fail the COMMIT if there is some other active statement.
Multi-threaded programs are better off using (at least) one connection per thread.