Maybe this sounds stupid, but I want to create a vector/array of SRWLocks dynamically during runtime. The following code compiles both ways, but the array thing doesn’t work. Probably the question should be, can I create an SRWLock object using the new operator?
If this is not how it’s done, what’s the right way to create an array of SRWLock objects?
#include "stdafx.h"
#include <ppl.h>
#include <Windows.h>
#include <iostream>
using namespace std;
#define NOT_WORKING
int _tmain(int argc, _TCHAR* argv[])
{
#ifdef NOT_WORKING
// The following doesn't work
SRWLOCK *lock = new SRWLOCK[2];
int a = 10;
AcquireSRWLockExclusive(&lock[0]);
cout<<"Exclusive Lock Acquired";
a++;
ReleaseSRWLockExclusive(&lock[0]);
// The following doesn't work either
/*
SRWLOCK *lock_n = new SRWLOCK;
AcquireSRWLockExclusive(lock_n);
cout<<"Exclusive Lock Acquired";
a++;
ReleaseSRWLockExclusive(lock_n);
*/
#else
// This works
SRWLOCK lock;
int a = 10;
AcquireSRWLockExclusive(&lock);
cout<<"Exclusive Lock Acquired";
a++;
ReleaseSRWLockExclusive(&lock);
#endif
cout<<"Value of a:"<<a;
cin.get();
return 0;
}
User1577008's own answer:
Got it! One needs to use the InitializeSRWLock() function when lock objects are created dynamically. Somebody paste this answer, and help me close this question.
Related
Assume the code below demonstrating a binary semaphore example.
In this example, we have a pthread that reads the source.txt and attempts to copy the content to destination.txt while locking it using a binary semaphore.
What happens in the comment section below without the semaphore?
#include <cstdlib>
#include <memory>
#include <filesystem>
#define _TIMESPEC_DEFINED
#include <pthread.h>
#include <semaphore.h>
#include <thread>
#include <valarray>
pthread_t StartFileAccessThread();
void *CopyFile(void *parameters);
int main(int argc, char* argv[])
{
pthread_t thread = StartFileAccessThread();
void *returnValue;
pthread_join(thread, &returnValue);
getchar();
return EXIT_SUCCESS;
}
pthread_t StartFileAccessThread()
{
std::string sourcePath("source.txt");
std::string destinationPath("dest.txt");
sem_t semaphore;
sem_init(&semaphore, 0, 0);
pthread_t thread;
void *parameters[3];
parameters[0] = &semaphore;
parameters[1] = &sourcePath;
parameters[2] = &destinationPath;
pthread_create(&thread, nullptr, &CopyFile, parameters);
// What happens without the binary semaphore?
sem_wait(&semaphore);
sem_destroy(&semaphore);
printf("Freeing ressources.\n");
return thread;
}
void *CopyFile(void *rawParameter)
{
void **parameters = static_cast<void **>(rawParameter);
sem_t *semaphore = static_cast<sem_t *>(parameters[0]);
std::string sourcePath(*static_cast<std::string *>(parameters[1]));
std::string destinationPath(*static_cast<std::string *>(parameters[2]));
sem_post(semaphore);
std::this_thread::sleep_for(std::chrono::seconds(2));
copy_file(sourcePath, destinationPath, std::experimental::filesystem::copy_options::overwrite_existing);
printf("File copied \n");
return nullptr;
}
What happens in the comment section below without the semaphore?
Without the semaphore, function startFileAccessThread() may return before the new thread finishes (or starts) copying its parameters from the argument object. That object is local to startFileAccessThread(), so its lifetime ends when that function returns. Undefined behavior results if the copy thread's accesses to it do not happen before that.
I know that it might be a stupid question but can you tell me why the following patch of code fails? I see nothing wrong. I am trying to read integers using scanf. I have included the necessary library, but when I run the program it crashes after I read the first s. Thank you.
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <vector>
using namespace std;
int main()
{
int n, x;
scanf("%d", &n); scanf("%d", &x);
vector< pair<int, int> > moments;
for(int i = 0; i < n; ++i)
{
int f, s;
scanf("%d", &f);
scanf("%d", &s );
moments[i].first = f;
moments[i].second = s;
}
return 0;
}
That is not the way to assign values to moments since moments[i] does not yet exist. Try:
pair<int, int> thing;
thing = make_pair(f,s);
moments.push_back(thing);
instead of your assignements to moments elements.
Please help to figure out whats wrong with this code.
main.cpp create Object3D which create Box and pass Object3D* pointer to Box.
And there are errors until i remove Object3D declarations from Box.
main.cpp
#include <iostream>
#include "stdafx.h"
#include "Object3D.h"
int _tmain(int argc, _TCHAR* argv[])
{
Object3D obj;
char c;
std::cin >> c;
return 0;
}
Object3D.cpp
#include "Object3D.h"
#include "Box.h"
Object3D::Object3D()
{}
Object3D::~Object3D()
{}
Object3D.h
#ifndef OBJECT3D_H
#define OBJECT3D_H
#include "Box.h"
class Object3D
{
public:
Object3D();
~Object3D();
private:
Box _box_obj; //<<<---ERROR HERE (C2146, C4430)
};
#endif
Box.cpp
#include "Box.h"
#include "Object3D.h"
int Box::Init(Object3D* _obj)
{
obj = _obj;
}
Box::Box()
{}
Box::~Box()
{}
Box.h
#ifndef BOX_H
#define BOX_H
#include "Object3D.h"
class Box
{
public:
Object3D* obj; //<<<---ERROR HERE (C2143, C4430)
int Init(Object3D* _obj); //<<<---ERROR HERE (C2061)
Box();
~Box();
};
#endif
Change Box.h:
#ifndef BOX_H
#define BOX_H
// forward reference possible since the class is not dereferenced here.
class Object3D;
class Box
{
public:
Object3D* obj;
int Init(Object3D* _obj);
Box();
~Box();
};
#endif
The class definition does not use any member of Object3D. Therefore you don't need to know the definition of Object3D but just the fact that it is a class. The forward reference is sufficient and an appropriate tool to resolve a circular dependency.
BTW: The circular reference of object usually includes some "master" objects that own the other objects. It makes sense to change the member name to show the relation rather the type. I would suggest a
Object3D* owner;
when the box owns the obj.
so somewhere along the lines of putting this app together I've started to get a runtime check failure stack corruption when the destructor for a cstring class member is called.
I've gotten to the point of trying to debug this by throwing bricks at the issue but still havent root caused it. At the current moment the class that the cstring resides in does nothing but initialize its private string members and set a pointer to another class to NULL.
Interestingly if I do not set the class pointer to NULL and comment out that line the corruption goes away. I think this is somewhat of a red herring, and that something is changing in the way the compiler is putting the code together when it pulls in the .h file that contains theCLog definitions and that would be used since I'm declaring a pointer to that object.
int _tmain(int argc, _TCHAR* argv[])
{
DWORD a = 0xBABA; //just to help catch the corrupter
DWORD b = 0xDFDF;
CStringW startat = L"\\\\anetworkshare\\fre";
CStringW lookfor = L".inf";
DirEnum myEnum(startat,lookfor);
ULONG en = a + b;
en = a - b;
return 0;
}
DirEnum.cpp
DirEnum::DirEnum(CString startingdir,CString fileFilter)
{
m_plogfile = NULL; //If you comment out this line corruption goes away
m_startingdir = L"";
m_extfilter = L"";
if(startingdir.GetLength() > 0)
m_startingdir = startingdir;
if(fileFilter.GetLength() > 0)
m_extfilter = fileFilter;
//following commented out to tshoot
//CLogBase& ref = ref.GetInstance();
//logBase = &ref;
//m_plogfile = new CLog(L"DirEnumerator",L"logfile.txt",logINFO);
}
Now I suspect that something in the log.h file is causing a change to occuur in the ATL or CString libraries but I dont know what. Heres the log.h file
#pragma once
//#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
using namespace std;
#ifndef TYPEDEF_H
#define TYPEDEF_H
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <tchar.h>
#include <time.h>
//simple defines to allow the TCHAR library to be used
typedef std::basic_string<TCHAR> tstring;
typedef std::basic_ostream<TCHAR> tostream;
typedef std::basic_istream<TCHAR> tistream;
typedef std::basic_ostringstream<TCHAR> tostringstream;
typedef std::basic_istringstream<TCHAR> tistringstream;
typedef std::basic_ofstream<TCHAR> tofstream;
#if defined(UNICODE) || defined(_UNICODE)
#define tcout std::wcout
#define tcin std::wcin
#else
#define tcout std::cout
#define tcin std::cin;
#endif
#endif
#if defined DEBUG || defined (_DEBUG)
#define TOCONSOLE
#endif
typedef enum LOGLVL{logERROR =0,logWARN,logINFO,logDEBUG};
//CLogBase os a singleton log class. Intent is that you can establish a reference from anywhere in the project and write to the same file
// without having locking issues or threading issues
class CLogBase
{
public:
static CLogBase& GetInstance(CString logname = L"log.txt",LOGLVL lvl = logWARN);
~CLogBase(void);
tostringstream& GetLog(LOGLVL level);
tostringstream& GetStream(LOGLVL);
void Forceflush();
private:
CLogBase(CString file,LOGLVL lvl);
//our outstream
tostringstream m_os;
tostringstream m_dummy;
tofstream m_filestream;
CString m_filename;
LOGLVL m_reportlvl;
//Private declarations to prevent copy constructors from being invoked; these are do nothig implimentations
CLogBase(CLogBase const&);
void operator=(CLogBase const&);
};
class CLog
{
public:
CLog(CString component);
CLog(CString component,CString logname,LOGLVL lvl);
~CLog();
void Log(LOGLVL,CString message);
void CLog::Flush();
tostringstream& CLog::GetStream(LOGLVL lvl);
private:
CString m_componentname;
CLogBase* m_logBase;
};
I thought I would answer this as I found the issue. this was not a coding problem per se but a visual studio issue.
What happened was that I was storing the direnum.h file and .cpp file in a different directory than the one used for the main project. referencing the header with #include "..\somedir\direnum.h"
at one point in time visual studio reported the file as locked and did I want to overwrite \ cancel etc. I choose overwrite but what seemed to happen was that this caused VS to COPY the files to the current project. All my troubleshooting attempts were being edited in the local somename.h file whtne opened in the editor but the compiler was doing the correct thing and pulling down the .h file from the location above.
removing switching to the now local copy of direnum.h and recompiling fixed this as it was compiling part of the code as ANSI and the other part as WCHAR
I am new to CUDA and I am getting a strange error. I want to print a string from a passed object and I get the error "calling host function from global function is not allowed" and I don't know why. But if I want to print an integer (changing get method to return sk1), everything works fine. Here is the code:
class Duomenys {
private:
string simb;
int sk1;
double sk2;
public:
__device__ __host__ Duomenys(void): simb(""), sk1(0), sk2(0.0) {}
__device__ __host__~Duomenys() {}
__device__ __host__ Duomenys::Duomenys(string simb1, int sk11, double sk21)
: simb(simb1), sk1(sk11), sk2(sk21) {}
__device__ __host__ string Duomenys::get(){
return simb;
}
};
And here I am calling Duomenys::get from __global__ function:
__global__ void Vec_add(Duomenys a) {
printf(" %s \n",a.get());
}
EDIT: I am trying to read data from a file and print it in a global function. In this code I am trying read all data and print just one object to see if everything works. This is the error I'm getting:
calling a __host__ function("std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string") from a __global__ function("Vec_add") is not allowed
Code:
#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
using namespace std;
class Duomenys {
private:
string simb;
int sk1;
double sk2;
public:
__device__ __host__ Duomenys(void): simb(""), sk1(0), sk2(0.0) {}
__device__ __host__~Duomenys() {}
__device__ __host__ Duomenys::Duomenys(string simb1, int sk11, double sk21)
: simb(simb1), sk1(sk11), sk2(sk21) {}
__device__ __host__ string Duomenys::print()
{
stringstream ss;
ss << left << setw(10) << simb << setw(10) << sk1 << setw(10) << sk2;
return ss.str();
}
};
__global__ void Vec_add(Duomenys a) {
printf(" %s \n",a.print());
}
/* Host code */
int main(int argc, char* argv[]) {
setlocale (LC_ALL,"");
vector<Duomenys> vienas;
vector<vector<Duomenys>> visi;
//data reading to vector "vienas" (it works without any errors)
Duomenys *darr;
const size_t sz = size_t(2) * sizeof(Duomenys);
cudaMalloc((void**)&darr, sz);
Vec_add<<<1, 1>>>(visi[0].at(0));
cudaDeviceSynchronize();
cudaMemcpy(darr, &visi[0].at(0), sz, cudaMemcpyHostToDevice);
return 0;
}
Your problem is not with printf function, but with string data type. You cannot use the C++ string type in a kernel. See related question here: Can we use the string data type in C++ within kernels
Why would you pass a string object to printf when the %s format specifier is expecting something else? When I try to do that in ordinary host code, I get warnings about "passing non-POD types through ellipsis (call will abort at runtime)". Note that this problem has nothing to do with CUDA.
But beyond that issue, presumably you're getting string from the C++ standard library. (It's better if you show a complete reproducer code, then I don't have to guess at where you're getting things or what you are including.)
If I get string as follows:
#include <string>
using namespace std;
Then I am using a function defined in the C++ Standard Library. CUDA supports the C++ language (mostly) but does not necessarily support usage of C++ libraries (or C libraries, for that matter) in device code. Libraries are (usually) composed of (at least some) compiled code (such as allocators, in this case), and this code has been compiled for CPUs, not for the GPU. When you try to use such a CPU compiled routine (e.g. an allocator associated with the string class) in device code, the compiler will bark at you. If you include the complete error message in the question, it will be more obvious specifically what (compiled-for-the-host) function is actually the issue.
Use a standard C style string instead (i.e. char[] and you will be able to use it directly in printf.
EDIT: In response to a question in the comments, here is a modified version of the code posted that demonstrates how to use an ordinary C-style string (i.e. char[]) and print from it in device code.
#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#define STRSZ 32
using namespace std;
class Duomenys {
private:
char simb[STRSZ];
int sk1;
double sk2;
public:
__device__ __host__ Duomenys(void): sk1(0), sk2(0.0) {}
__device__ __host__~Duomenys() {}
__device__ __host__ Duomenys(char *simb1, int sk11, double sk21)
: sk1(sk11), sk2(sk21) {}
__device__ __host__ char * print()
{
return simb;
}
__device__ __host__ void store_str(const char *str)
{
for (int i=0; i< STRSZ; i++)
simb[i] = str[i];
}
};
__global__ void Vec_add(Duomenys a) {
printf(" %s \n",a.print());
}
/* Host code */
int main(int argc, char* argv[]) {
string host_string("hello\n");
setlocale (LC_ALL,"");
vector<Duomenys> vienas(3);
vienas[0].store_str(host_string.c_str());
vector<vector<Duomenys> > visi(3);
visi[0] = vienas;
//data reading to vector "vienas" (it works without any errors)
Duomenys *darr;
const size_t sz = size_t(2) * sizeof(Duomenys);
cudaMalloc((void**)&darr, sz);
Vec_add<<<1, 1>>>(visi[0].at(0));
cudaDeviceSynchronize();
cudaMemcpy(darr, &(visi[0].at(0)), sz, cudaMemcpyHostToDevice);
return 0;
}
Note that I didn't try to understand your code or fix everything that looked strange to me. However this should demonstrate one possible approach.