summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-09-11 08:00:28 -0700
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-09-11 08:00:28 -0700
commit68fd128d82819db1022137a45ca3224cee8ef029 (patch)
tree6f01d5456d830de9d24150ec56e5c1ee4d464faa /src
parentf08f5850fa39c42974e12e42fa101ffe51eef594 (diff)
The environment object that is passed to functions now always is the same environment object, added move operator= to Value class to make moving zvals faster, and added request startup and request closedown methods
Diffstat (limited to 'src')
-rw-r--r--src/extension.cpp57
-rw-r--r--src/function.cpp5
-rw-r--r--src/includes.h2
-rw-r--r--src/value.cpp71
4 files changed, 94 insertions, 41 deletions
diff --git a/src/extension.cpp b/src/extension.cpp
index 37082b2..b0d78f2 100644
--- a/src/extension.cpp
+++ b/src/extension.cpp
@@ -26,42 +26,13 @@ namespace Php {
static Extension *extension = nullptr;
/**
- * The way how PHP C API deals with "global" variables is stupid.
- *
- * This is supposed to turn into a structure that is going to be
- * instantiated for each parallel running request, and for which the
- * PHP engine allocates a certain amount of memory, and a magic
- * pointer that is passed and should be forwarded to every thinkable
- * PHP function.
- *
- * We don't like this architecture. We have our own request object
- * that makes much more sense, and that we use. However, we need
- * to assign this object somewhere, so that's what we do in this
- * one and only global variable
- */
-ZEND_BEGIN_MODULE_GLOBALS(phpcpp)
- Environment *environment;
-ZEND_END_MODULE_GLOBALS(phpcpp)
-
-/**
- * And now we're going to define a macro. This also is a ridiculous
- * architecture from PHP to get access to a variable from the
- * structure above.
- */
-#ifdef ZTS
-#define PHPCPP_G(v) TSRMG(phpcpp_globals_id, zend_phpcpp_globals *, v)
-#else
-#define PHPCPP_G(v) (phpcpp_globals.v)
-#endif
-
-/**
* We're almost there, we now need to declare an instance of the
* structure defined above (if building for a single thread) or some
* sort of impossible to understand magic pointer-to-a-pointer (for
* multi-threading builds). We make this a static variable because
* this already is bad enough.
*/
-static ZEND_DECLARE_MODULE_GLOBALS(phpcpp)
+ZEND_DECLARE_MODULE_GLOBALS(phpcpp)
/**
* Function that must be defined to initialize the "globals"
@@ -71,8 +42,6 @@ static ZEND_DECLARE_MODULE_GLOBALS(phpcpp)
*/
static void init_globals(zend_phpcpp_globals *globals) {}
-
-
/**
* Function that is called when the extension initializes
* @param type Module type
@@ -109,10 +78,16 @@ static int extension_shutdown(SHUTDOWN_FUNC_ARGS)
static int request_startup(INIT_FUNC_ARGS)
{
// create the environment
- PHPCPP_G(environment) = extension->createEnvironment();
+ Environment *environment = extension->createEnvironment();
+
+ // store in global structure
+ PHPCPP_G(environment) = environment;
+
+ // initialize the environment
+ environment->initialize();
// start the request
- return BOOL2SUCCESS(extension->startRequest(*(PHPCPP_G(environment))));
+ return BOOL2SUCCESS(environment->initialize() && extension->startRequest(*environment));
}
/**
@@ -123,11 +98,17 @@ static int request_startup(INIT_FUNC_ARGS)
*/
static int request_shutdown(INIT_FUNC_ARGS)
{
+ // retrieve the environment
+ Environment *environment = PHPCPP_G(environment);
+
// end the request
- bool success = extension->endRequest(*(PHPCPP_G(environment)));
+ bool success = extension->endRequest(*environment) && environment->finalize();
// deallocate the environment
- extension->deleteEnvironment(PHPCPP_G(environment));
+ extension->deleteEnvironment(environment);
+
+ // reset global variable
+ PHPCPP_G(environment) = NULL;
// done
return BOOL2SUCCESS(success);
@@ -137,8 +118,10 @@ static int request_shutdown(INIT_FUNC_ARGS)
* Constructor
* @param name Name of the extension
* @param version Version number
+ * @param start Request start callback
+ * @param stop Request stop callback
*/
-Extension::Extension(const char *name, const char *version)
+Extension::Extension(const char *name, const char *version, request_callback start, request_callback stop) : _start(start), _stop(stop)
{
// store extension variable
extension = this;
diff --git a/src/function.cpp b/src/function.cpp
index 10b47b9..2afc1be 100644
--- a/src/function.cpp
+++ b/src/function.cpp
@@ -37,11 +37,8 @@ void invoke_function(INTERNAL_FUNCTION_PARAMETERS)
// construct parameters
Parameters params(ZEND_NUM_ARGS());
- // @todo get the appropriate request (or environment)
- Environment environment(NULL);
-
// get the result
- result = function->invoke(environment, params);
+ result = function->invoke(*PHPCPP_G(environment), params);
}
/**
diff --git a/src/includes.h b/src/includes.h
index cfcff2a..1a60b67 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -45,8 +45,10 @@
#include "../include/parameters.h"
#include "../include/function.h"
#include "../include/extension.h"
+#include "../include/globals.h"
/**
* Interface files for internal use only
*/
#include "nativefunction.h"
+
diff --git a/src/value.cpp b/src/value.cpp
index 7f43724..4cdac58 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -244,6 +244,77 @@ Value &Value::operator=(const Value &value)
}
/**
+ * Move operator
+ * @param value
+ * @return Value
+ */
+Value &Value::operator=(Value &&value)
+{
+ // skip self assignment
+ if (this == &value) return *this;
+
+ // is the object a reference?
+ if (Z_ISREF_P(_val))
+ {
+ // @todo difference if the other object is a reference or not?
+
+
+ // the current object is a reference, this means that we should
+ // keep the zval object, and copy the other value into it, get
+ // the current refcount
+ int refcount = Z_REFCOUNT_P(_val);
+
+ // clean up the current zval (but keep the zval structure)
+ zval_dtor(_val);
+
+ // make the copy
+ *_val = *value._val;
+
+ // restore reference and refcount setting
+ Z_SET_ISREF_TO_P(_val, true);
+ Z_SET_REFCOUNT_P(_val, refcount);
+
+ // how many references did the old variable have?
+ if (Z_ISREF_P(value._val) > 1)
+ {
+ // the other object already had multiple references, this
+ // implies that many other PHP variables are also referring
+ // to it, and we still need to store its contents, with one
+ // reference less
+ Z_DELREF_P(value._val);
+
+ // and we need to run the copy constructor on the current
+ // value, because we're making a deep copy
+ zval_copy_ctor(_val);
+ }
+ else
+ {
+ // the last and only reference to the other object was
+ // removed, we no longer need it
+ FREE_ZVAL(value._val);
+
+ // the other object is no longer valid
+ value._val = nullptr;
+ }
+ }
+ else
+ {
+ // destruct the zval (this function will decrement the reference counter,
+ // and only destruct if there are no other references left)
+ zval_ptr_dtor(&_val);
+
+ // just copy the zval completely
+ _val = value._val;
+
+ // the other object is no longer valid
+ value._val = nullptr;
+ }
+
+ // done
+ return *this;
+}
+
+/**
* Assignment operator
* @param value
* @return Value