feature/session (#3073): Rework locking mechanism & add Redis driver
diff --git a/system/libraries/Session/Session_driver.php b/system/libraries/Session/Session_driver.php
index cc35b66..a3bc392 100644
--- a/system/libraries/Session/Session_driver.php
+++ b/system/libraries/Session/Session_driver.php
@@ -90,12 +90,19 @@
 	protected $_match_ip;
 
 	/**
-	 * Data dash
+	 * Data fingerprint
 	 *
 	 * @var	bool
 	 */
 	protected $_fingerprint;
 
+	/**
+	 * Lock placeholder
+	 *
+	 * @var	mixed
+	 */
+	protected $_lock = FALSE;
+
 	// ------------------------------------------------------------------------
 
 	/**
@@ -202,6 +209,61 @@
 		);
 	}
 
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Get lock
+	 *
+	 * A default locking mechanism via semaphores, if ext/sysvsem is available.
+	 *
+	 * Drivers will usually override this and only fallback to it if no other
+	 * locking mechanism is available.
+	 *
+	 * @param	string	$session_id
+	 * @return	bool
+	 */
+	protected function _get_lock($session_id)
+	{
+		if ( ! extension_loaded('sysvsem'))
+		{
+			$this->_lock = TRUE;
+			return TRUE;
+		}
+
+		if (($this->_lock = sem_get($session_id.($this->_match_ip ? '_'.$_SERVER['REMOTE_ADDR'] : ''), 1, 0644)) === FALSE)
+		{
+			return FALSE;
+		}
+
+		if ( ! sem_acquire($this->_lock))
+		{
+			sem_remove($this->_lock);
+			$this->_lock = FALSE;
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Release lock
+	 *
+	 * @return	bool
+	 */
+	protected function _release_lock()
+	{
+		if (extension_loaded('sysvsem') && $this->_lock)
+		{
+			sem_release($this->_lock);
+			sem_remove($this->_lock);
+			$this->_lock = FALSE;
+		}
+
+		return TRUE;
+	}
+
 }
 
 /* End of file Session_driver.php */