mirror of
https://github.com/godotengine/godot.git
synced 2026-01-06 10:11:57 +03:00
GODOT IS OPEN SOURCE
This commit is contained in:
7
drivers/unix/SCsub
Normal file
7
drivers/unix/SCsub
Normal file
@@ -0,0 +1,7 @@
|
||||
Import('env')
|
||||
|
||||
env.add_source_files(env.drivers_sources,"*.cpp")
|
||||
|
||||
Export('env')
|
||||
|
||||
|
||||
312
drivers/unix/dir_access_unix.cpp
Normal file
312
drivers/unix/dir_access_unix.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
/*************************************************************************/
|
||||
/* dir_access_unix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "dir_access_unix.h"
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
|
||||
|
||||
#ifndef ANDROID_ENABLED
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "os/memory.h"
|
||||
#include "print_string.h"
|
||||
#include <errno.h>
|
||||
|
||||
DirAccess *DirAccessUnix::create_fs() {
|
||||
|
||||
return memnew( DirAccessUnix );
|
||||
}
|
||||
|
||||
bool DirAccessUnix::list_dir_begin() {
|
||||
|
||||
list_dir_end(); //close any previous dir opening!
|
||||
|
||||
|
||||
// char real_current_dir_name[2048]; //is this enough?!
|
||||
//getcwd(real_current_dir_name,2048);
|
||||
//chdir(curent_path.utf8().get_data());
|
||||
dir_stream = opendir(current_dir.utf8().get_data());
|
||||
//chdir(real_current_dir_name);
|
||||
if (!dir_stream)
|
||||
return true; //error!
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DirAccessUnix::file_exists(String p_file) {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION
|
||||
|
||||
|
||||
if (p_file.is_rel_path())
|
||||
p_file=current_dir+"/"+p_file;
|
||||
else
|
||||
p_file=fix_path(p_file);
|
||||
|
||||
struct stat flags;
|
||||
bool success = (stat(p_file.utf8().get_data(),&flags)==0);
|
||||
|
||||
if (success && S_ISDIR(flags.st_mode)) {
|
||||
success=false;
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
uint64_t DirAccessUnix::get_modified_time(String p_file) {
|
||||
|
||||
if (p_file.is_rel_path())
|
||||
p_file=current_dir+"/"+p_file;
|
||||
else
|
||||
p_file=fix_path(p_file);
|
||||
|
||||
struct stat flags;
|
||||
bool success = (stat(p_file.utf8().get_data(),&flags)==0);
|
||||
|
||||
if (success) {
|
||||
return flags.st_mtime;
|
||||
} else {
|
||||
|
||||
ERR_FAIL_V(0);
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
String DirAccessUnix::get_next() {
|
||||
|
||||
if (!dir_stream)
|
||||
return "";
|
||||
dirent *entry;
|
||||
|
||||
entry=readdir(dir_stream);
|
||||
|
||||
if (entry==NULL) {
|
||||
|
||||
list_dir_end();
|
||||
return "";
|
||||
}
|
||||
|
||||
//typedef struct stat Stat;
|
||||
struct stat flags;
|
||||
|
||||
String fname;
|
||||
if (fname.parse_utf8(entry->d_name))
|
||||
fname=entry->d_name; //no utf8, maybe latin?
|
||||
|
||||
String f=current_dir+"/"+fname;
|
||||
|
||||
if (stat(f.utf8().get_data(),&flags)==0) {
|
||||
|
||||
if (S_ISDIR(flags.st_mode)) {
|
||||
|
||||
_cisdir=true;
|
||||
|
||||
} else {
|
||||
|
||||
_cisdir=false;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
_cisdir=false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return fname;
|
||||
|
||||
}
|
||||
|
||||
bool DirAccessUnix::current_is_dir() const {
|
||||
|
||||
return _cisdir;
|
||||
}
|
||||
|
||||
|
||||
void DirAccessUnix::list_dir_end() {
|
||||
|
||||
if (dir_stream)
|
||||
closedir(dir_stream);
|
||||
dir_stream=0;
|
||||
_cisdir=false;
|
||||
}
|
||||
|
||||
int DirAccessUnix::get_drive_count() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
String DirAccessUnix::get_drive(int p_drive) {
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
Error DirAccessUnix::make_dir(String p_dir) {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION
|
||||
|
||||
p_dir=fix_path(p_dir);
|
||||
|
||||
char real_current_dir_name[2048];
|
||||
getcwd(real_current_dir_name,2048);
|
||||
chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
|
||||
|
||||
bool success=(mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)==0);
|
||||
int err = errno;
|
||||
|
||||
chdir(real_current_dir_name);
|
||||
|
||||
if (success) {
|
||||
return OK;
|
||||
};
|
||||
|
||||
if (err == EEXIST) {
|
||||
return ERR_ALREADY_EXISTS;
|
||||
};
|
||||
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
|
||||
|
||||
Error DirAccessUnix::change_dir(String p_dir) {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION
|
||||
p_dir=fix_path(p_dir);
|
||||
|
||||
|
||||
char real_current_dir_name[2048];
|
||||
getcwd(real_current_dir_name,2048);
|
||||
String prev_dir;
|
||||
if (prev_dir.parse_utf8(real_current_dir_name))
|
||||
prev_dir=real_current_dir_name; //no utf8, maybe latin?
|
||||
|
||||
chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
|
||||
bool worked=(chdir(p_dir.utf8().get_data())==0); // we can only give this utf8
|
||||
#ifndef IPHONE_ENABLED
|
||||
String base = _get_root_path();
|
||||
if (base!="") {
|
||||
|
||||
getcwd(real_current_dir_name,2048);
|
||||
String new_dir;
|
||||
new_dir.parse_utf8(real_current_dir_name);
|
||||
if (!new_dir.begins_with(base))
|
||||
worked=false;
|
||||
}
|
||||
#endif
|
||||
if (worked) {
|
||||
|
||||
getcwd(real_current_dir_name,2048);
|
||||
if (current_dir.parse_utf8(real_current_dir_name))
|
||||
current_dir=real_current_dir_name; //no utf8, maybe latin?
|
||||
}
|
||||
|
||||
chdir(prev_dir.utf8().get_data());
|
||||
return worked?OK:ERR_INVALID_PARAMETER;
|
||||
|
||||
}
|
||||
|
||||
String DirAccessUnix::get_current_dir() {
|
||||
|
||||
String base = _get_root_path();
|
||||
if (base!="") {
|
||||
|
||||
String bd = current_dir.replace_first(base,"");
|
||||
if (bd.begins_with("/"))
|
||||
return _get_root_string()+bd.substr(1,bd.length());
|
||||
else
|
||||
return _get_root_string()+bd;
|
||||
|
||||
}
|
||||
return current_dir;
|
||||
}
|
||||
|
||||
Error DirAccessUnix::rename(String p_path,String p_new_path) {
|
||||
|
||||
p_path=fix_path(p_path);
|
||||
p_new_path=fix_path(p_new_path);
|
||||
|
||||
return ::rename(p_path.utf8().get_data(),p_new_path.utf8().get_data())==0?OK:FAILED;
|
||||
}
|
||||
Error DirAccessUnix::remove(String p_path) {
|
||||
|
||||
p_path=fix_path(p_path);
|
||||
|
||||
struct stat flags;
|
||||
if ((stat(p_path.utf8().get_data(),&flags)!=0))
|
||||
return FAILED;
|
||||
|
||||
if (S_ISDIR(flags.st_mode))
|
||||
return ::rmdir(p_path.utf8().get_data())==0?OK:FAILED;
|
||||
else
|
||||
return ::unlink(p_path.utf8().get_data())==0?OK:FAILED;
|
||||
}
|
||||
|
||||
|
||||
size_t DirAccessUnix::get_space_left() {
|
||||
|
||||
#ifndef NO_STATVFS
|
||||
struct statvfs vfs;
|
||||
if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
return vfs.f_bfree * vfs.f_bsize;
|
||||
#else
|
||||
#warning THIS IS BROKEN
|
||||
return 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
DirAccessUnix::DirAccessUnix() {
|
||||
|
||||
dir_stream=0;
|
||||
current_dir=".";
|
||||
_cisdir=false;
|
||||
|
||||
/* determine drive count */
|
||||
|
||||
change_dir(current_dir);
|
||||
|
||||
}
|
||||
|
||||
|
||||
DirAccessUnix::~DirAccessUnix() {
|
||||
|
||||
list_dir_end();
|
||||
}
|
||||
|
||||
|
||||
#endif //posix_enabled
|
||||
88
drivers/unix/dir_access_unix.h
Normal file
88
drivers/unix/dir_access_unix.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*************************************************************************/
|
||||
/* dir_access_unix.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef DIR_ACCESS_UNIX_H
|
||||
#define DIR_ACCESS_UNIX_H
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "os/dir_access.h"
|
||||
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
class DirAccessUnix : public DirAccess {
|
||||
|
||||
DIR *dir_stream;
|
||||
|
||||
static DirAccess *create_fs();
|
||||
|
||||
String current_dir;
|
||||
bool _cisdir;
|
||||
|
||||
public:
|
||||
|
||||
virtual bool list_dir_begin(); ///< This starts dir listing
|
||||
virtual String get_next();
|
||||
virtual bool current_is_dir() const;
|
||||
|
||||
virtual void list_dir_end(); ///<
|
||||
|
||||
virtual int get_drive_count();
|
||||
virtual String get_drive(int p_drive);
|
||||
|
||||
virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
|
||||
virtual String get_current_dir(); ///< return current dir location
|
||||
virtual Error make_dir(String p_dir);
|
||||
|
||||
virtual bool file_exists(String p_file);
|
||||
virtual uint64_t get_modified_time(String p_file);
|
||||
|
||||
|
||||
|
||||
virtual Error rename(String p_from, String p_to);
|
||||
virtual Error remove(String p_name);
|
||||
|
||||
virtual size_t get_space_left();
|
||||
|
||||
|
||||
DirAccessUnix();
|
||||
~DirAccessUnix();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //UNIX ENABLED
|
||||
#endif
|
||||
257
drivers/unix/file_access_unix.cpp
Normal file
257
drivers/unix/file_access_unix.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
/*************************************************************************/
|
||||
/* file_access_unix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "file_access_unix.h"
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "print_string.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
#ifndef ANDROID_ENABLED
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
#ifdef MSVC
|
||||
#define S_ISREG(m) ((m)&_S_IFREG)
|
||||
#endif
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(m) ((m) & S_IFREG)
|
||||
#endif
|
||||
|
||||
void FileAccessUnix::check_errors() const {
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
|
||||
if (feof(f)) {
|
||||
|
||||
last_error=ERR_FILE_EOF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Error FileAccessUnix::_open(const String& p_path, int p_mode_flags) {
|
||||
|
||||
if (f)
|
||||
fclose(f);
|
||||
f=NULL;
|
||||
|
||||
String path=fix_path(p_path);
|
||||
//printf("opening %ls\n", path.c_str());
|
||||
|
||||
ERR_FAIL_COND_V(f,ERR_ALREADY_IN_USE);
|
||||
const char* mode_string;
|
||||
|
||||
if (p_mode_flags==READ)
|
||||
mode_string="rb";
|
||||
else if (p_mode_flags==WRITE)
|
||||
mode_string="wb";
|
||||
else if (p_mode_flags==READ_WRITE)
|
||||
mode_string="wb+";
|
||||
else
|
||||
return ERR_INVALID_PARAMETER;
|
||||
|
||||
/* pretty much every implementation that uses fopen as primary
|
||||
backend (unix-compatible mostly) supports utf8 encoding */
|
||||
|
||||
//printf("opening %s as %s\n", p_path.utf8().get_data(), path.utf8().get_data());
|
||||
struct stat st;
|
||||
if (stat(path.utf8().get_data(),&st) == 0) {
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return ERR_FILE_CANT_OPEN;
|
||||
|
||||
};
|
||||
|
||||
if (is_backup_save_enabled() && p_mode_flags&WRITE && !(p_mode_flags&READ)) {
|
||||
save_path=path;
|
||||
path=path+".tmp";
|
||||
//print_line("saving instead to "+path);
|
||||
}
|
||||
|
||||
f=fopen(path.utf8().get_data(),mode_string);
|
||||
|
||||
if (f==NULL) {
|
||||
last_error=ERR_FILE_CANT_OPEN;
|
||||
return ERR_FILE_CANT_OPEN;
|
||||
} else {
|
||||
last_error=OK;
|
||||
flags=p_mode_flags;
|
||||
return OK;
|
||||
}
|
||||
|
||||
}
|
||||
void FileAccessUnix::close() {
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
if (save_path!="") {
|
||||
|
||||
//unlink(save_path.utf8().get_data());
|
||||
//print_line("renaming..");
|
||||
int rename_error = rename((save_path+".tmp").utf8().get_data(),save_path.utf8().get_data());
|
||||
save_path="";
|
||||
ERR_FAIL_COND( rename_error != 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
bool FileAccessUnix::is_open() const{
|
||||
|
||||
return (f!=NULL);
|
||||
}
|
||||
void FileAccessUnix::seek(size_t p_position) {
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
|
||||
last_error=OK;
|
||||
if ( fseek(f,p_position,SEEK_SET) )
|
||||
check_errors();
|
||||
}
|
||||
void FileAccessUnix::seek_end(int64_t p_position) {
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
if ( fseek(f,p_position,SEEK_END) )
|
||||
check_errors();
|
||||
}
|
||||
size_t FileAccessUnix::get_pos() const{
|
||||
|
||||
|
||||
size_t aux_position=0;
|
||||
if ( !(aux_position = ftell(f)) ) {
|
||||
check_errors();
|
||||
};
|
||||
return aux_position;
|
||||
}
|
||||
size_t FileAccessUnix::get_len() const{
|
||||
|
||||
|
||||
ERR_FAIL_COND_V(!f,0);
|
||||
|
||||
FileAccessUnix *fau = const_cast<FileAccessUnix*>(this);
|
||||
int pos = fau->get_pos();
|
||||
fau->seek_end();
|
||||
int size = fau->get_pos();
|
||||
fau->seek(pos);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool FileAccessUnix::eof_reached() const{
|
||||
|
||||
return last_error==ERR_FILE_EOF;
|
||||
}
|
||||
|
||||
uint8_t FileAccessUnix::get_8() const{
|
||||
|
||||
ERR_FAIL_COND_V(!f,0);
|
||||
uint8_t b;
|
||||
if (fread(&b,1,1,f) == 0) {
|
||||
check_errors();
|
||||
};
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
int FileAccessUnix::get_buffer(uint8_t *p_dst, int p_length) const {
|
||||
|
||||
ERR_FAIL_COND_V(!f,-1);
|
||||
int read = fread(p_dst, 1, p_length, f);
|
||||
check_errors();
|
||||
return read;
|
||||
};
|
||||
|
||||
Error FileAccessUnix::get_error() const{
|
||||
|
||||
return last_error;
|
||||
}
|
||||
|
||||
void FileAccessUnix::store_8(uint8_t p_dest) {
|
||||
|
||||
ERR_FAIL_COND(!f);
|
||||
fwrite(&p_dest,1,1,f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool FileAccessUnix::file_exists(const String &p_path) {
|
||||
|
||||
FILE *g;
|
||||
//printf("opening file %s\n", p_fname.c_str());
|
||||
String filename=fix_path(p_path);
|
||||
g=fopen(filename.utf8().get_data(),"rb");
|
||||
if (g==NULL) {
|
||||
|
||||
return false;
|
||||
} else {
|
||||
|
||||
fclose(g);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
|
||||
|
||||
String file=fix_path(p_file);
|
||||
struct stat flags;
|
||||
bool success = (stat(file.utf8().get_data(),&flags)==0);
|
||||
|
||||
if (success) {
|
||||
return flags.st_mtime;
|
||||
} else {
|
||||
print_line("ERROR IN: "+p_file);
|
||||
|
||||
ERR_FAIL_V(0);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
FileAccess * FileAccessUnix::create_libc() {
|
||||
|
||||
return memnew( FileAccessUnix );
|
||||
}
|
||||
|
||||
|
||||
FileAccessUnix::FileAccessUnix() {
|
||||
|
||||
f=NULL;
|
||||
flags=0;
|
||||
last_error=OK;
|
||||
|
||||
}
|
||||
FileAccessUnix::~FileAccessUnix() {
|
||||
|
||||
close();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
81
drivers/unix/file_access_unix.h
Normal file
81
drivers/unix/file_access_unix.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*************************************************************************/
|
||||
/* file_access_unix.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef FILE_ACCESS_UNIX_H
|
||||
#define FILE_ACCESS_UNIX_H
|
||||
|
||||
#include "os/file_access.h"
|
||||
#include "os/memory.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
class FileAccessUnix : public FileAccess {
|
||||
|
||||
FILE *f;
|
||||
int flags;
|
||||
void check_errors() const;
|
||||
mutable Error last_error;
|
||||
String save_path;
|
||||
|
||||
static FileAccess* create_libc();
|
||||
public:
|
||||
|
||||
virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file
|
||||
virtual void close(); ///< close a file
|
||||
virtual bool is_open() const; ///< true when file is open
|
||||
|
||||
virtual void seek(size_t p_position); ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position=0); ///< seek from the end of file
|
||||
virtual size_t get_pos() const; ///< get position in the file
|
||||
virtual size_t get_len() const; ///< get size of the file
|
||||
|
||||
virtual bool eof_reached() const; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const; ///< get a byte
|
||||
virtual int get_buffer(uint8_t *p_dst, int p_length) const;
|
||||
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String& p_path); ///< return true if a file exists
|
||||
|
||||
virtual uint64_t _get_modified_time(const String& p_file);
|
||||
|
||||
FileAccessUnix();
|
||||
virtual ~FileAccessUnix();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
68
drivers/unix/ip_unix.cpp
Normal file
68
drivers/unix/ip_unix.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/*************************************************************************/
|
||||
/* ip_unix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "ip_unix.h"
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
#include <ws2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) {
|
||||
|
||||
struct hostent *he;
|
||||
if ((he=gethostbyname(p_hostname.utf8().get_data())) == NULL) { // get the host info
|
||||
ERR_PRINT("gethostbyname failed!");
|
||||
return IP_Address();
|
||||
}
|
||||
IP_Address ip;
|
||||
|
||||
ip.host= *((unsigned long*)he->h_addr);
|
||||
|
||||
return ip;
|
||||
|
||||
}
|
||||
|
||||
void IP_Unix::make_default() {
|
||||
|
||||
_create=_create_unix;
|
||||
}
|
||||
|
||||
IP* IP_Unix::_create_unix() {
|
||||
|
||||
return memnew( IP_Unix );
|
||||
}
|
||||
|
||||
IP_Unix::IP_Unix() {
|
||||
}
|
||||
|
||||
#endif
|
||||
49
drivers/unix/ip_unix.h
Normal file
49
drivers/unix/ip_unix.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*************************************************************************/
|
||||
/* ip_unix.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef IP_UNIX_H
|
||||
#define IP_UNIX_H
|
||||
|
||||
#include "io/ip.h"
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
|
||||
|
||||
class IP_Unix : public IP {
|
||||
OBJ_TYPE(IP_Unix, IP);
|
||||
|
||||
virtual IP_Address _resolve_hostname(const String& p_hostname);
|
||||
|
||||
static IP* _create_unix();
|
||||
public:
|
||||
|
||||
static void make_default();
|
||||
IP_Unix();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // IP_UNIX_H
|
||||
419
drivers/unix/memory_pool_static_malloc.cpp
Normal file
419
drivers/unix/memory_pool_static_malloc.cpp
Normal file
@@ -0,0 +1,419 @@
|
||||
/*************************************************************************/
|
||||
/* memory_pool_static_malloc.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "memory_pool_static_malloc.h"
|
||||
#include "error_macros.h"
|
||||
#include "os/memory.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "os/copymem.h"
|
||||
#include "os/os.h"
|
||||
|
||||
/**
|
||||
* NOTE NOTE NOTE NOTE
|
||||
* in debug mode, this prepends the memory size to the allocated block
|
||||
* so BE CAREFUL!
|
||||
*/
|
||||
|
||||
|
||||
void* MemoryPoolStaticMalloc::alloc(size_t p_bytes,const char *p_description) {
|
||||
|
||||
#if DFAULT_ALIGNMENT == 1
|
||||
|
||||
return _alloc(p_bytes, p_description);
|
||||
|
||||
#else
|
||||
|
||||
int total = p_bytes + DEFAULT_ALIGNMENT;
|
||||
uint8_t* ptr = (uint8_t*)_alloc(total, p_description);
|
||||
ERR_FAIL_COND_V( !ptr, ptr );
|
||||
int ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1)));
|
||||
ptr[ofs-1] = ofs;
|
||||
return (void*)(ptr + ofs);
|
||||
#endif
|
||||
};
|
||||
|
||||
void* MemoryPoolStaticMalloc::_alloc(size_t p_bytes,const char *p_description) {
|
||||
|
||||
ERR_FAIL_COND_V(p_bytes==0,0);
|
||||
|
||||
MutexLock lock(mutex);
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
void *mem=malloc(p_bytes+sizeof(RingPtr)); /// add for size and ringlist
|
||||
|
||||
if (!mem) {
|
||||
printf("**ERROR: out of memory while allocating %i bytes by %s?\n",(int) p_bytes, p_description);
|
||||
printf("**ERROR: memory usage is %i\n", (int)get_total_usage());
|
||||
};
|
||||
|
||||
ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request
|
||||
|
||||
/* setup the ringlist element */
|
||||
|
||||
RingPtr *ringptr = (RingPtr*)mem;
|
||||
|
||||
/* setup the ringlist element data (description and size ) */
|
||||
|
||||
ringptr->size = p_bytes;
|
||||
ringptr->descr=p_description;
|
||||
|
||||
if (ringlist) { /* existing ringlist */
|
||||
|
||||
/* assign next */
|
||||
ringptr->next = ringlist->next;
|
||||
ringlist->next = ringptr;
|
||||
/* assign prev */
|
||||
ringptr->prev = ringlist;
|
||||
ringptr->next->prev = ringptr;
|
||||
} else { /* non existing ringlist */
|
||||
|
||||
ringptr->next=ringptr;
|
||||
ringptr->prev=ringptr;
|
||||
ringlist=ringptr;
|
||||
|
||||
}
|
||||
|
||||
total_mem+=p_bytes;
|
||||
|
||||
/* update statistics */
|
||||
if (total_mem > max_mem )
|
||||
max_mem = total_mem;
|
||||
|
||||
total_pointers++;
|
||||
|
||||
if (total_pointers > max_pointers)
|
||||
max_pointers=total_pointers;
|
||||
|
||||
return ringptr + 1; /* return memory after ringptr */
|
||||
|
||||
#else
|
||||
void *mem=malloc(p_bytes);
|
||||
|
||||
ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request
|
||||
return mem;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void* MemoryPoolStaticMalloc::realloc(void *p_memory,size_t p_bytes) {
|
||||
|
||||
#if DFAULT_ALIGNMENT == 1
|
||||
|
||||
return _realloc(p_memory,p_bytes);
|
||||
#else
|
||||
if (!p_memory)
|
||||
return alloc(p_bytes);
|
||||
|
||||
int total = p_bytes + DEFAULT_ALIGNMENT;
|
||||
uint8_t* mem = (uint8_t*)p_memory;
|
||||
int ofs = *(mem-1);
|
||||
mem = mem - ofs;
|
||||
uint8_t* ptr = (uint8_t*)_realloc(mem, total);
|
||||
ERR_FAIL_COND_V(ptr == NULL, NULL);
|
||||
int new_ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1)));
|
||||
if (new_ofs != ofs) {
|
||||
|
||||
//printf("realloc moving %i bytes\n", p_bytes);
|
||||
movemem((ptr + new_ofs), (ptr + ofs), p_bytes);
|
||||
ptr[new_ofs-1] = new_ofs;
|
||||
};
|
||||
return ptr + new_ofs;
|
||||
#endif
|
||||
};
|
||||
|
||||
void* MemoryPoolStaticMalloc::_realloc(void *p_memory,size_t p_bytes) {
|
||||
|
||||
if (p_memory==NULL) {
|
||||
|
||||
return alloc( p_bytes );
|
||||
}
|
||||
|
||||
if (p_bytes<=0) {
|
||||
|
||||
this->free(p_memory);
|
||||
ERR_FAIL_COND_V( p_bytes < 0 , NULL );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MutexLock lock(mutex);
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
|
||||
RingPtr *ringptr = (RingPtr*)p_memory;
|
||||
ringptr--; /* go back an element to find the tingptr */
|
||||
|
||||
bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr);
|
||||
bool is_list = ( ringlist == ringptr );
|
||||
|
||||
|
||||
RingPtr *new_ringptr=(RingPtr*)::realloc(ringptr, p_bytes+sizeof(RingPtr));
|
||||
|
||||
ERR_FAIL_COND_V( new_ringptr == 0, NULL ); /// reallocation failed
|
||||
|
||||
/* actualize mem used */
|
||||
total_mem -= new_ringptr->size;
|
||||
new_ringptr->size = p_bytes;
|
||||
total_mem += new_ringptr->size;
|
||||
|
||||
if (total_mem > max_mem ) //update statistics
|
||||
max_mem = total_mem;
|
||||
|
||||
if (new_ringptr == ringptr )
|
||||
return ringptr + 1; // block didn't move, don't do anything
|
||||
|
||||
if (single_element) {
|
||||
|
||||
new_ringptr->next=new_ringptr;
|
||||
new_ringptr->prev=new_ringptr;
|
||||
} else {
|
||||
|
||||
new_ringptr->next->prev=new_ringptr;
|
||||
new_ringptr->prev->next=new_ringptr;
|
||||
}
|
||||
|
||||
if (is_list)
|
||||
ringlist=new_ringptr;
|
||||
|
||||
|
||||
return new_ringptr + 1;
|
||||
|
||||
#else
|
||||
return ::realloc( p_memory, p_bytes );
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryPoolStaticMalloc::free(void *p_ptr) {
|
||||
|
||||
ERR_FAIL_COND( !MemoryPoolStatic::get_singleton());
|
||||
|
||||
#if DFAULT_ALIGNMENT == 1
|
||||
|
||||
_free(p_ptr);
|
||||
#else
|
||||
|
||||
uint8_t* mem = (uint8_t*)p_ptr;
|
||||
int ofs = *(mem-1);
|
||||
mem = mem - ofs;
|
||||
|
||||
_free(mem);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void MemoryPoolStaticMalloc::_free(void *p_ptr) {
|
||||
|
||||
MutexLock lock(mutex);
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
if (p_ptr==0) {
|
||||
printf("**ERROR: STATIC ALLOC: Attempted free of NULL pointer.\n");
|
||||
return;
|
||||
};
|
||||
|
||||
RingPtr *ringptr = (RingPtr*)p_ptr;
|
||||
|
||||
ringptr--; /* go back an element to find the ringptr */
|
||||
|
||||
|
||||
#if 0
|
||||
{ // check for existing memory on free.
|
||||
RingPtr *p = ringlist;
|
||||
|
||||
bool found=false;
|
||||
|
||||
if (ringlist) {
|
||||
do {
|
||||
if (p==ringptr) {
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
|
||||
p=p->next;
|
||||
} while (p!=ringlist);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
printf("**ERROR: STATIC ALLOC: Attempted free of unknown pointer at %p\n",(ringptr+1));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
/* proceed to erase */
|
||||
|
||||
bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr);
|
||||
bool is_list = ( ringlist == ringptr );
|
||||
|
||||
if (single_element) {
|
||||
/* just get rid of it */
|
||||
ringlist=0;
|
||||
|
||||
} else {
|
||||
/* auto-remove from ringlist */
|
||||
if (is_list)
|
||||
ringlist=ringptr->next;
|
||||
|
||||
ringptr->prev->next = ringptr->next;
|
||||
ringptr->next->prev = ringptr->prev;
|
||||
}
|
||||
|
||||
total_mem -= ringptr->size;
|
||||
total_pointers--;
|
||||
// catch more errors
|
||||
zeromem(ringptr,sizeof(RingPtr)+ringptr->size);
|
||||
::free(ringptr); //just free that pointer
|
||||
|
||||
#else
|
||||
ERR_FAIL_COND(p_ptr==0);
|
||||
|
||||
::free(p_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
size_t MemoryPoolStaticMalloc::get_available_mem() const {
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
size_t MemoryPoolStaticMalloc::get_total_usage() {
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
return total_mem;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
size_t MemoryPoolStaticMalloc::get_max_usage() {
|
||||
|
||||
return max_mem;
|
||||
}
|
||||
|
||||
/* Most likely available only if memory debugger was compiled in */
|
||||
int MemoryPoolStaticMalloc::get_alloc_count() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
void * MemoryPoolStaticMalloc::get_alloc_ptr(int p_alloc_idx) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
const char* MemoryPoolStaticMalloc::get_alloc_description(int p_alloc_idx) {
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
size_t MemoryPoolStaticMalloc::get_alloc_size(int p_alloc_idx) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MemoryPoolStaticMalloc::dump_mem_to_file(const char* p_file) {
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */
|
||||
RingPtr *p = ringlist;
|
||||
FILE *f = fopen(p_file,"wb");
|
||||
|
||||
do {
|
||||
fprintf(f,"%p-%i-%s\n", p+1, (int)p->size, (p->descr?p->descr:"") );
|
||||
p=p->next;
|
||||
} while (p!=ringlist);
|
||||
|
||||
fclose(f);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
MemoryPoolStaticMalloc::MemoryPoolStaticMalloc() {
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
total_mem=0;
|
||||
total_pointers=0;
|
||||
ringlist=0;
|
||||
max_mem=0;
|
||||
max_pointers=0;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
mutex=NULL;
|
||||
#ifndef NO_THREADS
|
||||
|
||||
mutex=Mutex::create(); // at this point, this should work
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
MemoryPoolStaticMalloc::~MemoryPoolStaticMalloc() {
|
||||
|
||||
Mutex *old_mutex=mutex;
|
||||
mutex=NULL;
|
||||
if (old_mutex)
|
||||
memdelete(old_mutex);
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||
if (total_mem > 0 ) {
|
||||
printf("**ERROR: STATIC ALLOC: ** MEMORY LEAKS DETECTED **\n");
|
||||
printf("**ERROR: STATIC ALLOC: %i bytes of memory in use at exit.\n",(int)total_mem);
|
||||
|
||||
if (1){
|
||||
printf("**ERROR: STATIC ALLOC: Following is the list of leaked allocations: \n");
|
||||
|
||||
ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */
|
||||
RingPtr *p = ringlist;
|
||||
|
||||
do {
|
||||
printf("\t%p - %i bytes - %s\n", (RingPtr*)(p+1), (int)p->size, (p->descr?p->descr:"") );
|
||||
p=p->next;
|
||||
} while (p!=ringlist);
|
||||
|
||||
printf("**ERROR: STATIC ALLOC: End of Report.\n");
|
||||
};
|
||||
|
||||
printf("mem - max %i, pointers %i, leaks %i.\n",(int)max_mem,max_pointers,(int)total_mem);
|
||||
} else {
|
||||
|
||||
printf("INFO: mem - max %i, pointers %i, no leaks.\n",(int)max_mem,max_pointers);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
82
drivers/unix/memory_pool_static_malloc.h
Normal file
82
drivers/unix/memory_pool_static_malloc.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*************************************************************************/
|
||||
/* memory_pool_static_malloc.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef MEMORY_POOL_STATIC_MALLOC_H
|
||||
#define MEMORY_POOL_STATIC_MALLOC_H
|
||||
|
||||
#include "os/memory_pool_static.h"
|
||||
#include "os/mutex.h"
|
||||
/**
|
||||
@author Juan Linietsky <red@lunatea>
|
||||
*/
|
||||
class MemoryPoolStaticMalloc : public MemoryPoolStatic {
|
||||
|
||||
struct RingPtr {
|
||||
|
||||
size_t size;
|
||||
const char *descr; /* description of memory */
|
||||
RingPtr *next;
|
||||
RingPtr *prev;
|
||||
};
|
||||
|
||||
RingPtr *ringlist;
|
||||
size_t total_mem;
|
||||
int total_pointers;
|
||||
|
||||
size_t max_mem;
|
||||
int max_pointers;
|
||||
|
||||
Mutex *mutex;
|
||||
|
||||
void* _alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello"
|
||||
void* _realloc(void *p_memory,size_t p_bytes); ///< Pointer in
|
||||
void _free(void *p_ptr); ///< Pointer in p_description shold be to a const char const
|
||||
|
||||
public:
|
||||
|
||||
virtual void* alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello"
|
||||
virtual void free(void *p_ptr); ///< Pointer in p_description shold be to a const char const
|
||||
virtual void* realloc(void *p_memory,size_t p_bytes); ///< Pointer in
|
||||
virtual size_t get_available_mem() const;
|
||||
virtual size_t get_total_usage();
|
||||
virtual size_t get_max_usage();
|
||||
|
||||
/* Most likely available only if memory debugger was compiled in */
|
||||
virtual int get_alloc_count();
|
||||
virtual void * get_alloc_ptr(int p_alloc_idx);
|
||||
virtual const char* get_alloc_description(int p_alloc_idx);
|
||||
virtual size_t get_alloc_size(int p_alloc_idx);
|
||||
|
||||
void dump_mem_to_file(const char* p_file);
|
||||
|
||||
MemoryPoolStaticMalloc();
|
||||
~MemoryPoolStaticMalloc();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
73
drivers/unix/mutex_posix.cpp
Normal file
73
drivers/unix/mutex_posix.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*************************************************************************/
|
||||
/* mutex_posix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "mutex_posix.h"
|
||||
#include "os/memory.h"
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
|
||||
|
||||
void MutexPosix::lock() {
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
}
|
||||
void MutexPosix::unlock() {
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
Error MutexPosix::try_lock() {
|
||||
|
||||
return (pthread_mutex_trylock(&mutex)==0)?OK:ERR_BUSY;
|
||||
}
|
||||
|
||||
Mutex *MutexPosix::create_func_posix(bool p_recursive) {
|
||||
|
||||
return memnew( MutexPosix(p_recursive) );
|
||||
}
|
||||
|
||||
void MutexPosix::make_default() {
|
||||
|
||||
create_func=create_func_posix;
|
||||
}
|
||||
|
||||
MutexPosix::MutexPosix(bool p_recursive) {
|
||||
|
||||
pthread_mutexattr_init(&attr);
|
||||
if (p_recursive)
|
||||
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&mutex,&attr);
|
||||
}
|
||||
|
||||
|
||||
MutexPosix::~MutexPosix() {
|
||||
|
||||
pthread_mutex_destroy(&mutex);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
61
drivers/unix/mutex_posix.h
Normal file
61
drivers/unix/mutex_posix.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*************************************************************************/
|
||||
/* mutex_posix.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef MUTEX_POSIX_H
|
||||
#define MUTEX_POSIX_H
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
|
||||
|
||||
#include <pthread.h>
|
||||
#include "os/mutex.h"
|
||||
|
||||
class MutexPosix : public Mutex {
|
||||
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
static Mutex *create_func_posix(bool p_recursive);
|
||||
|
||||
public:
|
||||
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual Error try_lock();
|
||||
|
||||
|
||||
static void make_default();
|
||||
|
||||
MutexPosix(bool p_recursive);
|
||||
|
||||
~MutexPosix();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
410
drivers/unix/os_unix.cpp
Normal file
410
drivers/unix/os_unix.cpp
Normal file
@@ -0,0 +1,410 @@
|
||||
/*************************************************************************/
|
||||
/* os_unix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "os_unix.h"
|
||||
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
#include "memory_pool_static_malloc.h"
|
||||
#include "os/memory_pool_dynamic_static.h"
|
||||
#include "thread_posix.h"
|
||||
#include "semaphore_posix.h"
|
||||
#include "mutex_posix.h"
|
||||
#include "core/os/thread_dummy.h"
|
||||
|
||||
//#include "core/io/file_access_buffered_fa.h"
|
||||
#include "file_access_unix.h"
|
||||
#include "dir_access_unix.h"
|
||||
#include "tcp_server_posix.h"
|
||||
#include "stream_peer_tcp_posix.h"
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include "globals.h"
|
||||
void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
|
||||
|
||||
if (p_rationale && p_rationale[0]) {
|
||||
|
||||
print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
|
||||
print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
|
||||
|
||||
} else {
|
||||
print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
|
||||
print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OS_Unix::debug_break() {
|
||||
|
||||
assert(false);
|
||||
};
|
||||
|
||||
int OS_Unix::get_audio_driver_count() const {
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
const char * OS_Unix::get_audio_driver_name(int p_driver) const {
|
||||
|
||||
return "dummy";
|
||||
}
|
||||
|
||||
int OS_Unix::unix_initialize_audio(int p_audio_driver) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MemoryPoolStaticMalloc *mempool_static=NULL;
|
||||
static MemoryPoolDynamicStatic *mempool_dynamic=NULL;
|
||||
|
||||
|
||||
void OS_Unix::initialize_core() {
|
||||
|
||||
#ifdef NO_PTHREADS
|
||||
ThreadDummy::make_default();
|
||||
SemaphoreDummy::make_default();
|
||||
MutexDummy::make_default();
|
||||
#else
|
||||
ThreadPosix::make_default();
|
||||
SemaphorePosix::make_default();
|
||||
MutexPosix::make_default();
|
||||
#endif
|
||||
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
|
||||
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
|
||||
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
|
||||
//FileAccessBufferedFA<FileAccessUnix>::make_default();
|
||||
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES);
|
||||
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
|
||||
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
|
||||
|
||||
#ifndef NO_NETWORK
|
||||
TCPServerPosix::make_default();
|
||||
StreamPeerTCPPosix::make_default();
|
||||
IP_Unix::make_default();
|
||||
#endif
|
||||
mempool_static = new MemoryPoolStaticMalloc;
|
||||
mempool_dynamic = memnew( MemoryPoolDynamicStatic );
|
||||
|
||||
ticks_start=0;
|
||||
ticks_start=get_ticks_usec();
|
||||
}
|
||||
|
||||
void OS_Unix::finalize_core() {
|
||||
|
||||
|
||||
if (mempool_dynamic)
|
||||
memdelete( mempool_dynamic );
|
||||
if (mempool_static)
|
||||
delete mempool_static;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void OS_Unix::vprint(const char* p_format, va_list p_list,bool p_stder) {
|
||||
|
||||
if (p_stder) {
|
||||
|
||||
vfprintf(stderr,p_format,p_list);
|
||||
fflush(stderr);
|
||||
} else {
|
||||
|
||||
vprintf(p_format,p_list);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void OS_Unix::print(const char *p_format, ... ) {
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, p_format);
|
||||
vprintf(p_format, argp );
|
||||
va_end(argp);
|
||||
|
||||
}
|
||||
void OS_Unix::alert(const String& p_alert,const String& p_title) {
|
||||
|
||||
fprintf(stderr,"ERROR: %s\n",p_alert.utf8().get_data());
|
||||
}
|
||||
|
||||
static int has_data(FILE* p_fd, int timeout_usec = 0) {
|
||||
|
||||
fd_set readset;
|
||||
int fd = fileno(p_fd);
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(fd, &readset);
|
||||
timeval time;
|
||||
time.tv_sec = 0;
|
||||
time.tv_usec = timeout_usec;
|
||||
int res = 0;//select(fd + 1, &readset, NULL, NULL, &time);
|
||||
return res > 0;
|
||||
};
|
||||
|
||||
|
||||
String OS_Unix::get_stdin_string(bool p_block) {
|
||||
|
||||
String ret;
|
||||
if (p_block) {
|
||||
char buff[1024];
|
||||
ret = stdin_buf + fgets(buff,1024,stdin);
|
||||
stdin_buf = "";
|
||||
return ret;
|
||||
};
|
||||
|
||||
while (has_data(stdin)) {
|
||||
|
||||
char ch;
|
||||
read(fileno(stdin), &ch, 1);
|
||||
if (ch == '\n') {
|
||||
ret = stdin_buf;
|
||||
stdin_buf = "";
|
||||
return ret;
|
||||
} else {
|
||||
char str[2] = { ch, 0 };
|
||||
stdin_buf += str;
|
||||
};
|
||||
};
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
String OS_Unix::get_name() {
|
||||
|
||||
return "Unix";
|
||||
}
|
||||
|
||||
|
||||
uint64_t OS_Unix::get_unix_time() const {
|
||||
|
||||
return time(NULL);
|
||||
};
|
||||
|
||||
|
||||
OS::Date OS_Unix::get_date() const {
|
||||
|
||||
time_t t=time(NULL);
|
||||
struct tm *lt=localtime(&t);
|
||||
Date ret;
|
||||
ret.year=1900+lt->tm_year;
|
||||
ret.month=(Month)lt->tm_mon;
|
||||
ret.day=lt->tm_mday;
|
||||
ret.weekday=(Weekday)lt->tm_wday;
|
||||
ret.dst=lt->tm_isdst;
|
||||
|
||||
return ret;
|
||||
}
|
||||
OS::Time OS_Unix::get_time() const {
|
||||
|
||||
time_t t=time(NULL);
|
||||
struct tm *lt=localtime(&t);
|
||||
Time ret;
|
||||
ret.hour=lt->tm_hour;
|
||||
ret.min=lt->tm_min;
|
||||
ret.sec=lt->tm_sec;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void OS_Unix::delay_usec(uint32_t p_usec) const {
|
||||
|
||||
usleep(p_usec);
|
||||
}
|
||||
uint64_t OS_Unix::get_ticks_usec() const {
|
||||
|
||||
struct timeval tv_now;
|
||||
gettimeofday(&tv_now,NULL);
|
||||
|
||||
uint64_t longtime = (uint64_t)tv_now.tv_usec + (uint64_t)tv_now.tv_sec*1000000L;
|
||||
longtime-=ticks_start;
|
||||
|
||||
return longtime;
|
||||
}
|
||||
|
||||
Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id,String* r_pipe,int *r_exitcode) {
|
||||
|
||||
|
||||
if (p_blocking && r_pipe) {
|
||||
|
||||
|
||||
String argss;
|
||||
argss="\""+p_path+"\"";
|
||||
|
||||
for(int i=0;i<p_arguments.size();i++) {
|
||||
|
||||
argss+=String(" \"")+p_arguments[i]+"\"";
|
||||
}
|
||||
|
||||
argss+=" 2>/dev/null"; //silence stderr
|
||||
FILE* f=popen(argss.utf8().get_data(),"r");
|
||||
|
||||
ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
|
||||
|
||||
char buf[65535];
|
||||
while(fgets(buf,65535,f)) {
|
||||
|
||||
(*r_pipe)+=buf;
|
||||
}
|
||||
|
||||
int rv = pclose(f);
|
||||
if (r_exitcode)
|
||||
*r_exitcode=rv;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
pid_t pid = fork();
|
||||
ERR_FAIL_COND_V(pid<0,ERR_CANT_FORK);
|
||||
//print("execute: %s\n",p_path.utf8().get_data());
|
||||
|
||||
|
||||
if (pid==0) {
|
||||
// is child
|
||||
Vector<CharString> cs;
|
||||
cs.push_back(p_path.utf8());
|
||||
for(int i=0;i<p_arguments.size();i++)
|
||||
cs.push_back(p_arguments[i].utf8());
|
||||
|
||||
Vector<char*> args;
|
||||
for(int i=0;i<cs.size();i++)
|
||||
args.push_back((char*)cs[i].get_data());// shitty C cast
|
||||
args.push_back(0);
|
||||
|
||||
execv(p_path.utf8().get_data(),&args[0]);
|
||||
// still alive? something failed..
|
||||
fprintf(stderr,"**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n",p_path.utf8().get_data());
|
||||
abort();
|
||||
}
|
||||
|
||||
if (p_blocking) {
|
||||
|
||||
int status;
|
||||
pid_t rpid = waitpid(pid,&status,0);
|
||||
if (r_exitcode)
|
||||
*r_exitcode=WEXITSTATUS(status);
|
||||
|
||||
print("returned: %i, waiting for: %i\n",rpid,pid);
|
||||
} else {
|
||||
|
||||
if (r_child_id)
|
||||
*r_child_id=pid;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
Error OS_Unix::kill(const ProcessID& p_pid) {
|
||||
|
||||
int ret = ::kill(p_pid,SIGKILL);
|
||||
return ret?ERR_INVALID_PARAMETER:OK;
|
||||
}
|
||||
|
||||
bool OS_Unix::has_environment(const String& p_var) const {
|
||||
|
||||
return getenv(p_var.utf8().get_data())!=NULL;
|
||||
}
|
||||
|
||||
String OS_Unix::get_locale() const {
|
||||
|
||||
if (!has_environment("LANG"))
|
||||
return "en";
|
||||
|
||||
String locale = get_environment("LANG");
|
||||
int tp = locale.find(".");
|
||||
if (tp!=-1)
|
||||
locale=locale.substr(0,tp);
|
||||
return locale;
|
||||
}
|
||||
|
||||
Error OS_Unix::set_cwd(const String& p_cwd) {
|
||||
|
||||
if (chdir(p_cwd.utf8().get_data())!=0)
|
||||
return ERR_CANT_OPEN;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
String OS_Unix::get_environment(const String& p_var) const {
|
||||
|
||||
if (getenv(p_var.utf8().get_data()))
|
||||
return getenv(p_var.utf8().get_data());
|
||||
return "";
|
||||
}
|
||||
|
||||
int OS_Unix::get_processor_count() const {
|
||||
|
||||
return sysconf(_SC_NPROCESSORS_CONF);
|
||||
}
|
||||
|
||||
String OS_Unix::get_data_dir() const {
|
||||
|
||||
String an = Globals::get_singleton()->get("application/name");
|
||||
if (an!="") {
|
||||
|
||||
if (has_environment("HOME")) {
|
||||
|
||||
return get_environment("HOME")+"/."+an;
|
||||
}
|
||||
}
|
||||
|
||||
return Globals::get_singleton()->get_resource_path();
|
||||
|
||||
}
|
||||
|
||||
String OS_Unix::get_executable_path() const {
|
||||
|
||||
#ifdef __linux__
|
||||
//fix for running from a symlink
|
||||
char buf[256];
|
||||
memset(buf,0,256);
|
||||
readlink("/proc/self/exe", buf, sizeof(buf));
|
||||
//print_line("Exec path is:"+String(buf));
|
||||
String b = buf;
|
||||
if (b=="") {
|
||||
WARN_PRINT("Couldn't get executable path from /proc/self/exe, using argv[0]");
|
||||
return OS::get_executable_path();
|
||||
}
|
||||
return b;
|
||||
#else
|
||||
ERR_PRINT("Warning, don't know how to obtain executable path on this OS! Please override this function properly.");
|
||||
return OS::get_executable_path();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
121
drivers/unix/os_unix.h
Normal file
121
drivers/unix/os_unix.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*************************************************************************/
|
||||
/* os_unix.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef OS_UNIX_H
|
||||
#define OS_UNIX_H
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
|
||||
#include "os/os.h"
|
||||
#include "drivers/unix/ip_unix.h"
|
||||
|
||||
|
||||
class OS_Unix : public OS {
|
||||
|
||||
uint64_t ticks_start;
|
||||
protected:
|
||||
|
||||
// UNIX only handles the core functions.
|
||||
// inheriting platforms under unix (eg. X11) should handle the rest
|
||||
|
||||
//virtual int get_video_driver_count() const;
|
||||
//virtual const char * get_video_driver_name(int p_driver) const;
|
||||
//virtual VideoMode get_default_video_mode() const;
|
||||
|
||||
virtual int get_audio_driver_count() const;
|
||||
virtual const char * get_audio_driver_name(int p_driver) const;
|
||||
|
||||
virtual void initialize_core();
|
||||
virtual int unix_initialize_audio(int p_audio_driver);
|
||||
//virtual void initialize(int p_video_driver,int p_audio_driver);
|
||||
|
||||
//virtual void finalize();
|
||||
virtual void finalize_core();
|
||||
|
||||
String stdin_buf;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
virtual void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type=ERR_ERROR);
|
||||
|
||||
virtual void print(const char *p_format, ... );
|
||||
virtual void vprint(const char* p_format, va_list p_list,bool p_stderr=false);
|
||||
virtual void alert(const String& p_alert,const String& p_title="ALERT!");
|
||||
virtual String get_stdin_string(bool p_block);
|
||||
|
||||
//virtual void set_mouse_show(bool p_show);
|
||||
//virtual void set_mouse_grab(bool p_grab);
|
||||
//virtual bool is_mouse_grab_enabled() const = 0;
|
||||
//virtual void get_mouse_pos(int &x, int &y) const;
|
||||
//virtual void set_window_title(const String& p_title);
|
||||
|
||||
//virtual void set_video_mode(const VideoMode& p_video_mode);
|
||||
//virtual VideoMode get_video_mode() const;
|
||||
//virtual void get_fullscreen_mode_list(List<VideoMode> *p_list) const;
|
||||
|
||||
virtual Error set_cwd(const String& p_cwd);
|
||||
|
||||
virtual String get_name();
|
||||
|
||||
virtual Date get_date() const;
|
||||
virtual Time get_time() const;
|
||||
|
||||
virtual uint64_t get_unix_time() const;
|
||||
|
||||
virtual void delay_usec(uint32_t p_usec) const;
|
||||
virtual uint64_t get_ticks_usec() const;
|
||||
|
||||
virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL);
|
||||
virtual Error kill(const ProcessID& p_pid);
|
||||
|
||||
virtual bool has_environment(const String& p_var) const;
|
||||
virtual String get_environment(const String& p_var) const;
|
||||
virtual String get_locale() const;
|
||||
|
||||
virtual int get_processor_count() const;
|
||||
|
||||
|
||||
virtual void debug_break();
|
||||
|
||||
virtual String get_executable_path() const;
|
||||
virtual String get_data_dir() const;
|
||||
|
||||
//virtual void run( MainLoop * p_main_loop );
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
89
drivers/unix/semaphore_posix.cpp
Normal file
89
drivers/unix/semaphore_posix.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*************************************************************************/
|
||||
/* semaphore_posix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "semaphore_posix.h"
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
|
||||
|
||||
#include "os/memory.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
Error SemaphorePosix::wait() {
|
||||
|
||||
|
||||
while(sem_wait(&sem)) {
|
||||
if (errno==EINTR) {
|
||||
errno=0;
|
||||
continue;
|
||||
} else {
|
||||
perror("sem waiting");
|
||||
return ERR_BUSY;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error SemaphorePosix::post() {
|
||||
|
||||
return (sem_post(&sem)==0)?OK:ERR_BUSY;
|
||||
}
|
||||
int SemaphorePosix::get() const {
|
||||
|
||||
int val;
|
||||
sem_getvalue(&sem, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
Semaphore *SemaphorePosix::create_semaphore_posix() {
|
||||
|
||||
return memnew( SemaphorePosix );
|
||||
}
|
||||
|
||||
void SemaphorePosix::make_default() {
|
||||
|
||||
create_func=create_semaphore_posix;
|
||||
}
|
||||
|
||||
SemaphorePosix::SemaphorePosix() {
|
||||
|
||||
int r = sem_init(&sem,0,0);
|
||||
if (r != 0)
|
||||
perror("sem creating");
|
||||
}
|
||||
|
||||
|
||||
SemaphorePosix::~SemaphorePosix() {
|
||||
|
||||
sem_destroy(&sem);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
62
drivers/unix/semaphore_posix.h
Normal file
62
drivers/unix/semaphore_posix.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*************************************************************************/
|
||||
/* semaphore_posix.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef SEMAPHORE_POSIX_H
|
||||
#define SEMAPHORE_POSIX_H
|
||||
|
||||
|
||||
|
||||
#include "os/semaphore.h"
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
|
||||
|
||||
#include <semaphore.h>
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
class SemaphorePosix : public Semaphore {
|
||||
|
||||
mutable sem_t sem;
|
||||
|
||||
static Semaphore *create_semaphore_posix();
|
||||
|
||||
public:
|
||||
|
||||
virtual Error wait();
|
||||
virtual Error post();
|
||||
virtual int get() const;
|
||||
|
||||
static void make_default();
|
||||
SemaphorePosix();
|
||||
|
||||
~SemaphorePosix();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
388
drivers/unix/stream_peer_tcp_posix.cpp
Normal file
388
drivers/unix/stream_peer_tcp_posix.cpp
Normal file
@@ -0,0 +1,388 @@
|
||||
/*************************************************************************/
|
||||
/* stream_peer_tcp_posix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
#include "stream_peer_tcp_posix.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#ifndef NO_FCNTL
|
||||
#include <sys/fcntl.h>
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
|
||||
#define MSG_NOSIGNAL SO_NOSIGPIPE
|
||||
#endif
|
||||
|
||||
static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) {
|
||||
|
||||
their_addr.sin_family = AF_INET; // host byte order
|
||||
their_addr.sin_port = htons(p_port); // short, network byte order
|
||||
their_addr.sin_addr = *((struct in_addr*)&p_host.host);
|
||||
memset(&(their_addr.sin_zero), '\0', 8);
|
||||
};
|
||||
|
||||
StreamPeerTCP* StreamPeerTCPPosix::_create() {
|
||||
|
||||
return memnew(StreamPeerTCPPosix);
|
||||
};
|
||||
|
||||
void StreamPeerTCPPosix::make_default() {
|
||||
|
||||
StreamPeerTCP::_create = StreamPeerTCPPosix::_create;
|
||||
};
|
||||
|
||||
Error StreamPeerTCPPosix::_block(int p_sockfd, bool p_read, bool p_write) const {
|
||||
|
||||
struct pollfd pfd;
|
||||
pfd.fd = p_sockfd;
|
||||
pfd.events = 0;
|
||||
if (p_read)
|
||||
pfd.events |= POLLIN;
|
||||
if (p_write)
|
||||
pfd.events |= POLLOUT;
|
||||
pfd.revents = 0;
|
||||
|
||||
int ret = poll(&pfd, 1, -1);
|
||||
return ret < 0 ? FAILED : OK;
|
||||
};
|
||||
|
||||
Error StreamPeerTCPPosix::_poll_connection(bool p_block) const {
|
||||
|
||||
ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == -1, FAILED);
|
||||
|
||||
if (p_block) {
|
||||
|
||||
_block(sockfd, false, true);
|
||||
};
|
||||
|
||||
struct sockaddr_in their_addr;
|
||||
set_addr_in(their_addr, peer_host, peer_port);
|
||||
if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) {
|
||||
|
||||
if (errno == EISCONN) {
|
||||
status = STATUS_CONNECTED;
|
||||
return OK;
|
||||
};
|
||||
|
||||
return OK;
|
||||
} else {
|
||||
|
||||
status = STATUS_CONNECTED;
|
||||
return OK;
|
||||
};
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port) {
|
||||
|
||||
sockfd = p_sockfd;
|
||||
#ifndef NO_FCNTL
|
||||
fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||
#else
|
||||
int bval = 1;
|
||||
ioctl(sockfd, FIONBIO, &bval);
|
||||
|
||||
#endif
|
||||
status = STATUS_CONNECTING;
|
||||
|
||||
peer_host = p_host;
|
||||
peer_port = p_port;
|
||||
};
|
||||
|
||||
Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) {
|
||||
|
||||
ERR_FAIL_COND_V( p_host.host == 0, ERR_INVALID_PARAMETER);
|
||||
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||
ERR_PRINT("Socket creation failed!");
|
||||
disconnect();
|
||||
//perror("socket");
|
||||
return FAILED;
|
||||
};
|
||||
|
||||
#ifndef NO_FCNTL
|
||||
fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||
#else
|
||||
int bval = 1;
|
||||
ioctl(sockfd, FIONBIO, &bval);
|
||||
#endif
|
||||
|
||||
struct sockaddr_in their_addr;
|
||||
set_addr_in(their_addr, p_host, p_port);
|
||||
|
||||
errno = 0;
|
||||
if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1 && errno != EINPROGRESS) {
|
||||
|
||||
ERR_PRINT("Connection to remote host failed!");
|
||||
disconnect();
|
||||
return FAILED;
|
||||
};
|
||||
|
||||
if (errno == EINPROGRESS) {
|
||||
status = STATUS_CONNECTING;
|
||||
} else {
|
||||
status = STATUS_CONNECTED;
|
||||
};
|
||||
|
||||
peer_host = p_host;
|
||||
peer_port = p_port;
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
Error StreamPeerTCPPosix::write(const uint8_t* p_data,int p_bytes, int &r_sent, bool p_block) {
|
||||
|
||||
if (status == STATUS_NONE || status == STATUS_ERROR) {
|
||||
|
||||
return FAILED;
|
||||
};
|
||||
|
||||
if (status != STATUS_CONNECTED) {
|
||||
|
||||
if (_poll_connection(p_block) != OK) {
|
||||
|
||||
return FAILED;
|
||||
};
|
||||
|
||||
if (status != STATUS_CONNECTED) {
|
||||
r_sent = 0;
|
||||
return OK;
|
||||
};
|
||||
};
|
||||
|
||||
int data_to_send = p_bytes;
|
||||
const uint8_t *offset = p_data;
|
||||
if (sockfd == -1) return FAILED;
|
||||
errno = 0;
|
||||
int total_sent = 0;
|
||||
|
||||
while (data_to_send) {
|
||||
|
||||
int sent_amount = send(sockfd, offset, data_to_send, MSG_NOSIGNAL);
|
||||
//printf("Sent TCP data of %d bytes, errno %d\n", sent_amount, errno);
|
||||
|
||||
if (sent_amount == -1) {
|
||||
|
||||
if (errno != EAGAIN) {
|
||||
|
||||
perror("shit?");
|
||||
disconnect();
|
||||
ERR_PRINT("Server disconnected!\n");
|
||||
return FAILED;
|
||||
};
|
||||
|
||||
if (!p_block) {
|
||||
r_sent = total_sent;
|
||||
return OK;
|
||||
};
|
||||
|
||||
_block(sockfd, false, true);
|
||||
} else {
|
||||
|
||||
data_to_send -= sent_amount;
|
||||
offset += sent_amount;
|
||||
total_sent += sent_amount;
|
||||
};
|
||||
}
|
||||
|
||||
r_sent = total_sent;
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
Error StreamPeerTCPPosix::read(uint8_t* p_buffer, int p_bytes,int &r_received, bool p_block) {
|
||||
|
||||
if (!is_connected()) {
|
||||
|
||||
return FAILED;
|
||||
};
|
||||
|
||||
if (status == STATUS_CONNECTING) {
|
||||
|
||||
if (_poll_connection(p_block) != OK) {
|
||||
|
||||
return FAILED;
|
||||
};
|
||||
|
||||
if (status != STATUS_CONNECTED) {
|
||||
r_received = 0;
|
||||
return OK;
|
||||
};
|
||||
};
|
||||
|
||||
int to_read = p_bytes;
|
||||
int total_read = 0;
|
||||
errno = 0;
|
||||
|
||||
while (to_read) {
|
||||
|
||||
int read = recv(sockfd, p_buffer + total_read, to_read, 0);
|
||||
|
||||
if (read == -1) {
|
||||
|
||||
if (errno != EAGAIN) {
|
||||
|
||||
perror("shit?");
|
||||
disconnect();
|
||||
ERR_PRINT("Server disconnected!\n");
|
||||
return FAILED;
|
||||
};
|
||||
|
||||
if (!p_block) {
|
||||
|
||||
r_received = total_read;
|
||||
return OK;
|
||||
};
|
||||
_block(sockfd, true, false);
|
||||
|
||||
} else if (read==0) {
|
||||
|
||||
sockfd=-1;
|
||||
status = STATUS_NONE;
|
||||
peer_port = 0;
|
||||
peer_host = IP_Address();
|
||||
return ERR_FILE_EOF;
|
||||
|
||||
} else {
|
||||
|
||||
to_read -= read;
|
||||
total_read += read;
|
||||
};
|
||||
};
|
||||
|
||||
r_received = total_read;
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
void StreamPeerTCPPosix::set_nodelay(bool p_enabled) {
|
||||
|
||||
ERR_FAIL_COND(!is_connected());
|
||||
int flag=p_enabled?1:0;
|
||||
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int));
|
||||
}
|
||||
|
||||
bool StreamPeerTCPPosix::is_connected() const {
|
||||
|
||||
if (status == STATUS_NONE || status == STATUS_ERROR) {
|
||||
|
||||
return false;
|
||||
};
|
||||
if (status != STATUS_CONNECTED) {
|
||||
return true;
|
||||
};
|
||||
|
||||
return (sockfd!=-1);
|
||||
};
|
||||
|
||||
StreamPeerTCP::Status StreamPeerTCPPosix::get_status() const {
|
||||
|
||||
if (status == STATUS_CONNECTING) {
|
||||
_poll_connection(false);
|
||||
};
|
||||
|
||||
return status;
|
||||
};
|
||||
|
||||
|
||||
void StreamPeerTCPPosix::disconnect() {
|
||||
|
||||
if (sockfd != -1)
|
||||
close(sockfd);
|
||||
sockfd=-1;
|
||||
|
||||
status = STATUS_NONE;
|
||||
peer_port = 0;
|
||||
peer_host = IP_Address();
|
||||
};
|
||||
|
||||
|
||||
Error StreamPeerTCPPosix::put_data(const uint8_t* p_data,int p_bytes) {
|
||||
|
||||
int total;
|
||||
return write(p_data, p_bytes, total, true);
|
||||
};
|
||||
|
||||
Error StreamPeerTCPPosix::put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent) {
|
||||
|
||||
return write(p_data, p_bytes, r_sent, false);
|
||||
};
|
||||
|
||||
Error StreamPeerTCPPosix::get_data(uint8_t* p_buffer, int p_bytes) {
|
||||
|
||||
int total;
|
||||
return read(p_buffer, p_bytes, total, true);
|
||||
};
|
||||
|
||||
Error StreamPeerTCPPosix::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received) {
|
||||
|
||||
return read(p_buffer, p_bytes, r_received, false);
|
||||
};
|
||||
|
||||
IP_Address StreamPeerTCPPosix::get_connected_host() const {
|
||||
|
||||
return peer_host;
|
||||
};
|
||||
|
||||
uint16_t StreamPeerTCPPosix::get_connected_port() const {
|
||||
|
||||
return peer_port;
|
||||
};
|
||||
|
||||
StreamPeerTCPPosix::StreamPeerTCPPosix() {
|
||||
|
||||
sockfd = -1;
|
||||
status = STATUS_NONE;
|
||||
peer_port = 0;
|
||||
};
|
||||
|
||||
StreamPeerTCPPosix::~StreamPeerTCPPosix() {
|
||||
|
||||
disconnect();
|
||||
};
|
||||
|
||||
#endif
|
||||
89
drivers/unix/stream_peer_tcp_posix.h
Normal file
89
drivers/unix/stream_peer_tcp_posix.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*************************************************************************/
|
||||
/* stream_peer_tcp_posix.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
#ifndef STREAM_PEER_TCP_POSIX_H
|
||||
#define STREAM_PEER_TCP_POSIX_H
|
||||
|
||||
#include "core/io/ip_address.h"
|
||||
#include "core/io/stream_peer_tcp.h"
|
||||
#include "error_list.h"
|
||||
|
||||
#include "core/io/ip_address.h"
|
||||
|
||||
class StreamPeerTCPPosix : public StreamPeerTCP {
|
||||
|
||||
protected:
|
||||
|
||||
mutable Status status;
|
||||
|
||||
int sockfd;
|
||||
|
||||
Error _block(int p_sockfd, bool p_read, bool p_write) const;
|
||||
|
||||
Error _poll_connection(bool p_block) const;
|
||||
|
||||
IP_Address peer_host;
|
||||
int peer_port;
|
||||
|
||||
Error write(const uint8_t* p_data,int p_bytes, int &r_sent, bool p_block);
|
||||
Error read(uint8_t* p_buffer, int p_bytes,int &r_received, bool p_block);
|
||||
|
||||
static StreamPeerTCP* _create();
|
||||
|
||||
public:
|
||||
|
||||
virtual Error connect(const IP_Address& p_host, uint16_t p_port);
|
||||
|
||||
virtual Error put_data(const uint8_t* p_data,int p_bytes);
|
||||
virtual Error put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent);
|
||||
|
||||
virtual Error get_data(uint8_t* p_buffer, int p_bytes);
|
||||
virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received);
|
||||
|
||||
void set_socket(int p_sockfd, IP_Address p_host, int p_port);
|
||||
|
||||
virtual IP_Address get_connected_host() const;
|
||||
virtual uint16_t get_connected_port() const;
|
||||
|
||||
virtual bool is_connected() const;
|
||||
virtual Status get_status() const;
|
||||
virtual void disconnect();
|
||||
|
||||
virtual void set_nodelay(bool p_enabled);
|
||||
|
||||
static void make_default();
|
||||
|
||||
StreamPeerTCPPosix();
|
||||
~StreamPeerTCPPosix();
|
||||
};
|
||||
|
||||
#endif // TCP_CLIENT_POSIX_H
|
||||
|
||||
#endif
|
||||
178
drivers/unix/tcp_server_posix.cpp
Normal file
178
drivers/unix/tcp_server_posix.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*************************************************************************/
|
||||
/* tcp_server_posix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "tcp_server_posix.h"
|
||||
#include "stream_peer_tcp_posix.h"
|
||||
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#ifndef NO_FCNTL
|
||||
#include <sys/fcntl.h>
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <assert.h>
|
||||
TCP_Server* TCPServerPosix::_create() {
|
||||
|
||||
return memnew(TCPServerPosix);
|
||||
};
|
||||
|
||||
void TCPServerPosix::make_default() {
|
||||
|
||||
TCP_Server::_create = TCPServerPosix::_create;
|
||||
};
|
||||
|
||||
Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_hosts) {
|
||||
|
||||
printf("********* listening on port %i\n", p_port);
|
||||
int sockfd;
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
ERR_FAIL_COND_V(sockfd == -1, FAILED);
|
||||
#ifndef NO_FCNTL
|
||||
fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||
#else
|
||||
int bval = 1;
|
||||
ioctl(sockfd, FIONBIO, &bval);
|
||||
#endif
|
||||
|
||||
int reuse=1;
|
||||
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
|
||||
|
||||
printf("REUSEADDR failed!");
|
||||
}
|
||||
|
||||
struct sockaddr_in my_addr;
|
||||
my_addr.sin_family = AF_INET; // host byte order
|
||||
my_addr.sin_port = htons(p_port); // short, network byte order
|
||||
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts
|
||||
memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
|
||||
|
||||
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != -1) {
|
||||
|
||||
if (::listen(sockfd, 1) == -1) {
|
||||
|
||||
close(sockfd);
|
||||
ERR_FAIL_V(FAILED);
|
||||
};
|
||||
};
|
||||
|
||||
if (listen_sockfd != -1) {
|
||||
|
||||
printf("FAILED\n");
|
||||
stop();
|
||||
};
|
||||
|
||||
listen_sockfd = sockfd;
|
||||
|
||||
printf("OK! %i\n", listen_sockfd);
|
||||
return OK;
|
||||
};
|
||||
|
||||
bool TCPServerPosix::is_connection_available() const {
|
||||
|
||||
if (listen_sockfd == -1) {
|
||||
return false;
|
||||
};
|
||||
|
||||
struct pollfd pfd;
|
||||
pfd.fd = listen_sockfd;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
int ret = poll(&pfd, 1, 0);
|
||||
ERR_FAIL_COND_V(ret < 0, FAILED);
|
||||
|
||||
if (ret && (pfd.revents & POLLIN)) {
|
||||
printf("has connection!\n");
|
||||
return true;
|
||||
};
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Ref<StreamPeerTCP> TCPServerPosix::take_connection() {
|
||||
|
||||
if (!is_connection_available()) {
|
||||
return Ref<StreamPeerTCP>();
|
||||
};
|
||||
|
||||
struct sockaddr_in their_addr;
|
||||
socklen_t sin_size = sizeof(their_addr);
|
||||
int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size);
|
||||
ERR_FAIL_COND_V(fd == -1, Ref<StreamPeerTCP>());
|
||||
#ifndef NO_FCNTL
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
#else
|
||||
int bval = 1;
|
||||
ioctl(fd, FIONBIO, &bval);
|
||||
#endif
|
||||
|
||||
Ref<StreamPeerTCPPosix> conn = memnew(StreamPeerTCPPosix);
|
||||
IP_Address ip;
|
||||
ip.host = (uint32_t)their_addr.sin_addr.s_addr;
|
||||
conn->set_socket(fd, ip, ntohs(their_addr.sin_port));
|
||||
|
||||
return conn;
|
||||
};
|
||||
|
||||
void TCPServerPosix::stop() {
|
||||
|
||||
if (listen_sockfd != -1) {
|
||||
print_line("CLOSING CONNECTION");
|
||||
int ret = close(listen_sockfd);
|
||||
ERR_FAIL_COND(ret!=0);
|
||||
};
|
||||
|
||||
listen_sockfd = -1;
|
||||
};
|
||||
|
||||
|
||||
TCPServerPosix::TCPServerPosix() {
|
||||
|
||||
listen_sockfd = -1;
|
||||
};
|
||||
|
||||
TCPServerPosix::~TCPServerPosix() {
|
||||
|
||||
stop();
|
||||
};
|
||||
#endif
|
||||
57
drivers/unix/tcp_server_posix.h
Normal file
57
drivers/unix/tcp_server_posix.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*************************************************************************/
|
||||
/* tcp_server_posix.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef TCP_SERVER_POSIX_H
|
||||
#define TCP_SERVER_POSIX_H
|
||||
|
||||
#ifdef UNIX_ENABLED
|
||||
#include "core/io/tcp_server.h"
|
||||
|
||||
class TCPServerPosix : public TCP_Server {
|
||||
|
||||
int listen_sockfd;
|
||||
|
||||
static TCP_Server* _create();
|
||||
|
||||
public:
|
||||
|
||||
virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL);
|
||||
virtual bool is_connection_available() const;
|
||||
virtual Ref<StreamPeerTCP> take_connection();
|
||||
|
||||
virtual void stop();
|
||||
|
||||
static void make_default();
|
||||
|
||||
TCPServerPosix();
|
||||
~TCPServerPosix();
|
||||
};
|
||||
|
||||
|
||||
#endif // TCP_SERVER_POSIX_H
|
||||
#endif
|
||||
99
drivers/unix/thread_posix.cpp
Normal file
99
drivers/unix/thread_posix.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/*************************************************************************/
|
||||
/* thread_posix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "thread_posix.h"
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
|
||||
|
||||
#include "os/memory.h"
|
||||
|
||||
Thread::ID ThreadPosix::get_ID() const {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
Thread* ThreadPosix::create_thread_posix() {
|
||||
|
||||
return memnew( ThreadPosix );
|
||||
}
|
||||
|
||||
void *ThreadPosix::thread_callback(void *userdata) {
|
||||
|
||||
ThreadPosix *t=reinterpret_cast<ThreadPosix*>(userdata);
|
||||
t->callback(t->user);
|
||||
t->id=(ID)pthread_self();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Thread* ThreadPosix::create_func_posix(ThreadCreateCallback p_callback,void *p_user,const Settings&) {
|
||||
|
||||
ThreadPosix *tr= memnew(ThreadPosix);
|
||||
tr->callback=p_callback;
|
||||
tr->user=p_user;
|
||||
pthread_attr_init(&tr->pthread_attr);
|
||||
pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);
|
||||
|
||||
return tr;
|
||||
}
|
||||
Thread::ID ThreadPosix::get_thread_ID_func_posix() {
|
||||
|
||||
return (ID)pthread_self();
|
||||
}
|
||||
void ThreadPosix::wait_to_finish_func_posix(Thread* p_thread) {
|
||||
|
||||
ThreadPosix *tp=static_cast<ThreadPosix*>(p_thread);
|
||||
ERR_FAIL_COND(!tp);
|
||||
ERR_FAIL_COND(tp->pthread==0);
|
||||
|
||||
pthread_join(tp->pthread,NULL);
|
||||
tp->pthread=0;
|
||||
}
|
||||
|
||||
|
||||
void ThreadPosix::make_default() {
|
||||
|
||||
create_func=create_func_posix;
|
||||
get_thread_ID_func=get_thread_ID_func_posix;
|
||||
wait_to_finish_func=wait_to_finish_func_posix;
|
||||
|
||||
}
|
||||
|
||||
ThreadPosix::ThreadPosix() {
|
||||
|
||||
pthread=0;
|
||||
}
|
||||
|
||||
|
||||
ThreadPosix::~ThreadPosix() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
75
drivers/unix/thread_posix.h
Normal file
75
drivers/unix/thread_posix.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*************************************************************************/
|
||||
/* thread_posix.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef THREAD_POSIX_H
|
||||
#define THREAD_POSIX_H
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
#include "os/thread.h"
|
||||
|
||||
class ThreadPosix : public Thread {
|
||||
|
||||
pthread_t pthread;
|
||||
pthread_attr_t pthread_attr;
|
||||
ThreadCreateCallback callback;
|
||||
void *user;
|
||||
ID id;
|
||||
|
||||
static Thread* create_thread_posix();
|
||||
|
||||
|
||||
static void *thread_callback(void *userdata);
|
||||
|
||||
static Thread* create_func_posix(ThreadCreateCallback p_callback,void *,const Settings&);
|
||||
static ID get_thread_ID_func_posix();
|
||||
static void wait_to_finish_func_posix(Thread* p_thread);
|
||||
|
||||
ThreadPosix();
|
||||
public:
|
||||
|
||||
|
||||
virtual ID get_ID() const;
|
||||
|
||||
static void make_default();
|
||||
|
||||
|
||||
~ThreadPosix();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user