Commit fd6db821 authored by Davis King's avatar Davis King
Browse files

Made it so the matrix only uses matlab's allocation routines for matrices that

are directly the arguments of a mex function.  This way, we avoid the problem
of dlib::matrix objects being created in other threads that internally call
into matlab and mess it up (since matlab is not thread safe in any sense).
parent 3748650a
This diff is collapsed.
...@@ -1174,8 +1174,8 @@ namespace dlib ...@@ -1174,8 +1174,8 @@ namespace dlib
{ {
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
// You can't move memory around when compiled in a matlab mex file and the // You can't move memory around when compiled in a matlab mex file and the
// different locations have different persistence settings. // different locations have different ownership settings.
if (data._private_is_persistent() == item.data._private_is_persistent()) if (data._private_is_owned_by_matlab() == item.data._private_is_owned_by_matlab())
{ {
swap(item); swap(item);
} }
...@@ -1195,8 +1195,8 @@ namespace dlib ...@@ -1195,8 +1195,8 @@ namespace dlib
{ {
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
// You can't move memory around when compiled in a matlab mex file and the // You can't move memory around when compiled in a matlab mex file and the
// different locations have different persistence settings. // different locations have different ownership settings.
if (data._private_is_persistent() == rhs.data._private_is_persistent()) if (data._private_is_owned_by_matlab() == rhs.data._private_is_owned_by_matlab())
{ {
swap(rhs); swap(rhs);
} }
...@@ -1343,14 +1343,14 @@ namespace dlib ...@@ -1343,14 +1343,14 @@ namespace dlib
return data._private_release_mxArray(); return data._private_release_mxArray();
} }
void _private_mark_non_persistent() void _private_mark_owned_by_matlab()
{ {
data._private_mark_non_persistent(); data._private_mark_owned_by_matlab();
} }
bool _private_is_persistent() bool _private_is_owned_by_matlab()
{ {
return data._private_is_persistent(); return data._private_is_owned_by_matlab();
} }
#endif #endif
......
...@@ -187,8 +187,8 @@ namespace dlib ...@@ -187,8 +187,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
private: private:
...@@ -257,8 +257,8 @@ namespace dlib ...@@ -257,8 +257,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
private: private:
...@@ -339,8 +339,8 @@ namespace dlib ...@@ -339,8 +339,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
private: private:
...@@ -424,8 +424,8 @@ namespace dlib ...@@ -424,8 +424,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
private: private:
...@@ -511,8 +511,8 @@ namespace dlib ...@@ -511,8 +511,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
private: private:
T* data; T* data;
...@@ -634,8 +634,8 @@ namespace dlib ...@@ -634,8 +634,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
private: private:
...@@ -704,8 +704,8 @@ namespace dlib ...@@ -704,8 +704,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
private: private:
...@@ -786,8 +786,8 @@ namespace dlib ...@@ -786,8 +786,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
private: private:
...@@ -871,8 +871,8 @@ namespace dlib ...@@ -871,8 +871,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
private: private:
...@@ -938,8 +938,8 @@ namespace dlib ...@@ -938,8 +938,8 @@ namespace dlib
#ifdef MATLAB_MEX_FILE #ifdef MATLAB_MEX_FILE
void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); } void _private_set_mxArray ( mxArray* ) { DLIB_CASSERT(false, "This function should never be called."); }
mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); } mxArray* _private_release_mxArray(){DLIB_CASSERT(false, "This function should never be called."); }
void _private_mark_non_persistent() {DLIB_CASSERT(false, "This function should never be called."); } void _private_mark_owned_by_matlab() {DLIB_CASSERT(false, "This function should never be called."); }
bool _private_is_persistent() const { return true; } bool _private_is_owned_by_matlab() const { return false; }
#endif #endif
long nr ( long nr (
...@@ -981,9 +981,11 @@ namespace dlib ...@@ -981,9 +981,11 @@ namespace dlib
const static long NC = num_cols; const static long NC = num_cols;
layout ( layout (
): data(0), nr_(0), nc_(0), make_persistent(true),set_by_private_set_mxArray(false),mem(0) { } ): data(0), nr_(0), nc_(0), owned_by_matlab(false),set_by_private_set_mxArray(false),mem(0) { }
~layout () ~layout ()
{
if (owned_by_matlab)
{ {
if (!set_by_private_set_mxArray && mem) if (!set_by_private_set_mxArray && mem)
{ {
...@@ -992,6 +994,12 @@ namespace dlib ...@@ -992,6 +994,12 @@ namespace dlib
data = 0; data = 0;
} }
} }
else if (data)
{
delete [] data;
data = 0;
}
}
double& operator() ( double& operator() (
long r, long r,
...@@ -1015,9 +1023,11 @@ namespace dlib ...@@ -1015,9 +1023,11 @@ namespace dlib
mxArray* mem_ mxArray* mem_
) )
{ {
DLIB_CASSERT(mem == 0 && data == 0,"You can't call this function on an already allocated matrix.");
// We don't own the pointer, so make note of that so we won't try to free // We don't own the pointer, so make note of that so we won't try to free
// it. // it.
set_by_private_set_mxArray = true; set_by_private_set_mxArray = true;
owned_by_matlab = true;
mem = mem_; mem = mem_;
data = mxGetPr(mem); data = mxGetPr(mem);
nr_ = mxGetM(mem); nr_ = mxGetM(mem);
...@@ -1026,7 +1036,7 @@ namespace dlib ...@@ -1026,7 +1036,7 @@ namespace dlib
mxArray* _private_release_mxArray() mxArray* _private_release_mxArray()
{ {
DLIB_CASSERT(!make_persistent,""); DLIB_CASSERT(owned_by_matlab,"");
mxArray* temp = mem; mxArray* temp = mem;
mem = 0; mem = 0;
set_by_private_set_mxArray = false; set_by_private_set_mxArray = false;
...@@ -1036,21 +1046,21 @@ namespace dlib ...@@ -1036,21 +1046,21 @@ namespace dlib
return temp; return temp;
} }
void _private_mark_non_persistent() void _private_mark_owned_by_matlab()
{ {
DLIB_CASSERT(mem == 0,"You can't convert a persistent matlab array to non-persistent."); DLIB_CASSERT(mem == 0 && data == 0,"You can't say a matrix should be owned by matlab after it's been allocated.");
make_persistent = false; owned_by_matlab = true;
} }
bool _private_is_persistent() const bool _private_is_owned_by_matlab() const
{ {
return make_persistent; return owned_by_matlab;
} }
void swap( void swap(
layout& item layout& item
) )
{ {
std::swap(item.make_persistent,make_persistent); std::swap(item.owned_by_matlab,owned_by_matlab);
std::swap(item.set_by_private_set_mxArray,set_by_private_set_mxArray); std::swap(item.set_by_private_set_mxArray,set_by_private_set_mxArray);
std::swap(item.mem,mem); std::swap(item.mem,mem);
std::swap(item.data,data); std::swap(item.data,data);
...@@ -1068,6 +1078,8 @@ namespace dlib ...@@ -1068,6 +1078,8 @@ namespace dlib
long nr, long nr,
long nc long nc
) )
{
if (owned_by_matlab)
{ {
if (!set_by_private_set_mxArray && mem) if (!set_by_private_set_mxArray && mem)
{ {
...@@ -1080,9 +1092,14 @@ namespace dlib ...@@ -1080,9 +1092,14 @@ namespace dlib
mem = mxCreateDoubleMatrix(nr, nc, mxREAL); mem = mxCreateDoubleMatrix(nr, nc, mxREAL);
if (mem == 0) if (mem == 0)
throw std::bad_alloc(); throw std::bad_alloc();
if (make_persistent)
mexMakeArrayPersistent(mem);
data = mxGetPr(mem); data = mxGetPr(mem);
}
else
{
if (data)
delete [] data;
data = new double[nr*nc];
}
nr_ = nr; nr_ = nr;
nc_ = nc; nc_ = nc;
} }
...@@ -1091,7 +1108,7 @@ namespace dlib ...@@ -1091,7 +1108,7 @@ namespace dlib
double* data; double* data;
long nr_; long nr_;
long nc_; long nc_;
bool make_persistent; bool owned_by_matlab;
bool set_by_private_set_mxArray; bool set_by_private_set_mxArray;
mxArray* mem; mxArray* mem;
}; };
...@@ -1107,9 +1124,11 @@ namespace dlib ...@@ -1107,9 +1124,11 @@ namespace dlib
const static long NC = num_cols; const static long NC = num_cols;
layout ( layout (
): data(0), nr_(0), nc_(0), make_persistent(true),set_by_private_set_mxArray(false),mem(0) { } ): data(0), nr_(0), nc_(0), owned_by_matlab(false),set_by_private_set_mxArray(false),mem(0) { }
~layout () ~layout ()
{
if (owned_by_matlab)
{ {
if (!set_by_private_set_mxArray && mem) if (!set_by_private_set_mxArray && mem)
{ {
...@@ -1118,6 +1137,12 @@ namespace dlib ...@@ -1118,6 +1137,12 @@ namespace dlib
data = 0; data = 0;
} }
} }
else if (data)
{
delete [] data;
data = 0;
}
}
float& operator() ( float& operator() (
long r, long r,
...@@ -1141,9 +1166,11 @@ namespace dlib ...@@ -1141,9 +1166,11 @@ namespace dlib
mxArray* mem_ mxArray* mem_
) )
{ {
DLIB_CASSERT(mem == 0 && data == 0,"You can't call this function on an already allocated matrix.");
// We don't own the pointer, so make note of that so we won't try to free // We don't own the pointer, so make note of that so we won't try to free
// it. // it.
set_by_private_set_mxArray = true; set_by_private_set_mxArray = true;
owned_by_matlab = true;
mem = mem_; mem = mem_;
data = (float*)mxGetData(mem); data = (float*)mxGetData(mem);
nr_ = mxGetM(mem); nr_ = mxGetM(mem);
...@@ -1152,7 +1179,7 @@ namespace dlib ...@@ -1152,7 +1179,7 @@ namespace dlib
mxArray* _private_release_mxArray() mxArray* _private_release_mxArray()
{ {
DLIB_CASSERT(!make_persistent,""); DLIB_CASSERT(owned_by_matlab,"");
mxArray* temp = mem; mxArray* temp = mem;
mem = 0; mem = 0;
set_by_private_set_mxArray = false; set_by_private_set_mxArray = false;
...@@ -1162,21 +1189,21 @@ namespace dlib ...@@ -1162,21 +1189,21 @@ namespace dlib
return temp; return temp;
} }
void _private_mark_non_persistent() void _private_mark_owned_by_matlab()
{ {
DLIB_CASSERT(mem == 0,"You can't convert a persistent matlab array to non-persistent."); DLIB_CASSERT(mem == 0 && data == 0,"You can't say a matrix should be owned by matlab after it's been allocated.");
make_persistent = false; owned_by_matlab = true;
} }
bool _private_is_persistent() const bool _private_is_owned_by_matlab() const
{ {
return make_persistent; return owned_by_matlab;
} }
void swap( void swap(
layout& item layout& item
) )
{ {
std::swap(item.make_persistent,make_persistent); std::swap(item.owned_by_matlab,owned_by_matlab);
std::swap(item.set_by_private_set_mxArray,set_by_private_set_mxArray); std::swap(item.set_by_private_set_mxArray,set_by_private_set_mxArray);
std::swap(item.mem,mem); std::swap(item.mem,mem);
std::swap(item.data,data); std::swap(item.data,data);
...@@ -1194,6 +1221,8 @@ namespace dlib ...@@ -1194,6 +1221,8 @@ namespace dlib
long nr, long nr,
long nc long nc
) )
{
if (owned_by_matlab)
{ {
if (!set_by_private_set_mxArray && mem) if (!set_by_private_set_mxArray && mem)
{ {
...@@ -1206,9 +1235,14 @@ namespace dlib ...@@ -1206,9 +1235,14 @@ namespace dlib
mem = mxCreateNumericMatrix(nr, nc, mxSINGLE_CLASS, mxREAL); mem = mxCreateNumericMatrix(nr, nc, mxSINGLE_CLASS, mxREAL);
if (mem == 0) if (mem == 0)
throw std::bad_alloc(); throw std::bad_alloc();
if (make_persistent)
mexMakeArrayPersistent(mem);
data = (float*)mxGetData(mem); data = (float*)mxGetData(mem);
}
else
{
if (data)
delete [] data;
data = new float[nr*nc];
}
nr_ = nr; nr_ = nr;
nc_ = nc; nc_ = nc;
} }
...@@ -1217,7 +1251,7 @@ namespace dlib ...@@ -1217,7 +1251,7 @@ namespace dlib
float* data; float* data;
long nr_; long nr_;
long nc_; long nc_;
bool make_persistent; bool owned_by_matlab;
bool set_by_private_set_mxArray; bool set_by_private_set_mxArray;
mxArray* mem; mxArray* mem;
}; };
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment