00001 #include "Image.h"
00002 #include <stdlib.h>
00003 #include <stdio.h>
00004 #include "Time.h"
00005
00006 namespace FCam {
00007
00008 unsigned char *Image::Discard = (unsigned char *)(0);
00009 unsigned char *Image::AutoAllocate = (unsigned char *)(-1);
00010
00011 Image::Image()
00012 : size(0, 0), type(UNKNOWN), data(Image::Discard), refCount(NULL),
00013 mutex(NULL), weak(true), holdingLock(false) {
00014 }
00015
00016 Image::Image(int w, int h, ImageFormat f)
00017 : size(w, h), type(f), data(NULL), refCount(NULL), mutex(NULL),
00018 weak(false), holdingLock(false) {
00019 setData(new unsigned char[w*h*bytesPerPixel(f)]);
00020 refCount = new unsigned;
00021 *refCount = 1;
00022 }
00023
00024 Image::Image(Size s, ImageFormat f)
00025 : size(s), type(f), data(NULL), refCount(NULL), mutex(NULL),
00026 weak(false), holdingLock(false) {
00027 setData(new unsigned char[s.width*s.height*bytesPerPixel(f)]);
00028 refCount = new unsigned;
00029 *refCount = 1;
00030 }
00031
00032 Image::Image(Size s, ImageFormat f, unsigned char *d)
00033 : size(s), type(f), data(NULL), refCount(NULL), mutex(NULL),
00034 weak(true), holdingLock(false) {
00035 setData(d);
00036 if (valid()) {
00037 refCount = new unsigned;
00038 *refCount = 2;
00039 }
00040 }
00041
00042 Image::Image(int w, int h, ImageFormat f, unsigned char *d)
00043 : size(w, h), type(f), data(NULL), refCount(NULL), mutex(NULL),
00044 weak(true), holdingLock(false) {
00045 setData(d);
00046 if (valid()) {
00047 refCount = new unsigned;
00048 *refCount = 2;
00049 }
00050 }
00051
00052 Image::~Image() {
00053 setData(NULL);
00054 }
00055
00056 Image::Image(const Image &other)
00057 : size(other.size), type(other.type), data(other.data), refCount(other.refCount),
00058 mutex(other.mutex), weak(other.weak), holdingLock(false) {
00059 if (refCount) {
00060 (*refCount)++;
00061 }
00062 };
00063
00064 const Image &Image::operator=(const Image &other) {
00065 if (this == &other) return (*this);
00066 if (refCount && refCount == other.refCount) return (*this);
00067
00068 setData(NULL);
00069
00070
00071
00072 *(const_cast<unsigned char **>(&data)) = other.data;
00073 size = other.size;
00074 type = other.type;
00075 refCount = other.refCount;
00076 mutex = other.mutex;
00077 weak = other.weak;
00078 if (refCount) (*refCount)++;
00079 holdingLock = false;
00080
00081 return (*this);
00082 }
00083
00084 void Image::setData(unsigned char *d) {
00085
00086 if (holdingLock) pthread_mutex_unlock(mutex);
00087 holdingLock = false;
00088
00089 if (mutex && refCount && (*refCount == 0 || (weak && *refCount == 1))) {
00090 pthread_mutex_destroy(mutex);
00091 delete mutex;
00092 mutex = NULL;
00093 }
00094
00095 if (refCount) {
00096 (*refCount)--;
00097
00098 if (*refCount == 0) {
00099 delete refCount;
00100 delete[] data;
00101 }
00102 refCount = NULL;
00103 mutex = NULL;
00104 }
00105
00106
00107
00108 *(const_cast<unsigned char **>(&data)) = d;
00109
00110 if (valid()) {
00111 mutex = new pthread_mutex_t;
00112 pthread_mutex_init(mutex, NULL);
00113 }
00114
00115
00116 }
00117
00118 bool Image::lock(int timeout) {
00119 if (holdingLock) {
00120 printf("ERROR: image reference trying to acquire lock it's already "
00121 "holding. Make a separate image reference per thread.\n");
00122 } else if (!mutex) {
00123 printf("ERROR: locking an image with no mutex\n");
00124 debug();
00125 holdingLock = false;
00126 } else if (timeout < 0) {
00127 pthread_mutex_lock(mutex);
00128 holdingLock = true;
00129 } else if (timeout == 0) {
00130 int ret = pthread_mutex_trylock(mutex);
00131 holdingLock = (ret == 0);
00132 } else {
00133 struct timespec t = (struct timespec)(Time::now() + timeout);
00134 int ret = pthread_mutex_timedlock(mutex, &t);
00135 holdingLock = (ret == 0);
00136 }
00137
00138 return holdingLock;
00139 }
00140
00141 void Image::unlock() {
00142 if (!holdingLock) {
00143 printf("ERROR: cannot unlock a lock not held by this image reference\n");
00144 return;
00145 }
00146 if (!mutex) {
00147 printf("ERROR: unlocking an image with no mutex\n");
00148 debug();
00149 return;
00150 }
00151 pthread_mutex_unlock(mutex);
00152 holdingLock = false;
00153 }
00154
00155
00156 }
00157
00158
00159
00160