List:Commits« Previous MessageNext Message »
From:Konstantin Osipov Date:June 17 2009 9:58pm
Subject:Re: bzr commit into mysql-azalea branch (tor.didriksen:3357)
View as plain text  
* Tor Didriksen <Tor.Didriksen@stripped> [09/06/17 12:19]:
>  3357 Tor Didriksen	2009-06-16
>       http://bugs.mysql.com/bug.php?id=45523

Please add a bug title and describe the idea of the fix.

E.g. :

Bug#45523 "Objects of class base_ilist should not be copyable".

Suppress the compiler-generated public copy constructor
and assignment operator of class base_ilist; instead, implement
move_elements() method that would transfer ownership of elements
from one list to another. 


Notice the style in which I wrote bug id above: Bug#XXX triggers
various automatic actions upon commit, so it's better to stick to
it.


> 
>     modified:
>       sql/sp_head.cc
>       sql/sql_cursor.cc
>       sql/sql_list.h
>       sql/sql_prepare.cc

Normally we write per-file comments as well. Your change is small,
so perhaps they are not necessary, but usually we're pretty
verbose.


> === modified file 'sql/sp_head.cc'
> --- a/sql/sp_head.cc	2009-06-12 02:01:08 +0000
> +++ b/sql/sp_head.cc	2009-06-16 13:17:15 +0000
> @@ -1174,8 +1174,7 @@ sp_head::execute(THD *thd)
>      We should also save Item tree change list to avoid rollback something
>      too early in the calling query.
>    */
> -  old_change_list= thd->change_list;
> -  thd->change_list.empty();
> +  thd->change_list.move_elements(&old_change_list);

OK.

>    /*
>      Cursors will use thd->packet, so they may corrupt data which was prepared
>      for sending by upper level. OTOH cursors in the same routine can share this
> @@ -1321,9 +1320,7 @@ sp_head::execute(THD *thd)
>    /* Restore all saved */
>    old_packet.swap(thd->packet);
>    DBUG_ASSERT(thd->change_list.is_empty());
> -  thd->change_list= old_change_list;
> -  /* To avoid wiping out thd->change_list on old_change_list destruction */
> -  old_change_list.empty();
> +  old_change_list.move_elements(&thd->change_list);

OK.

>    thd->lex= old_lex;
>    thd->query_id= old_query_id;
>    DBUG_ASSERT(!thd->derived_tables);
> 
> === modified file 'sql/sql_cursor.cc'
> --- a/sql/sql_cursor.cc	2009-01-26 16:03:39 +0000
> +++ b/sql/sql_cursor.cc	2009-06-16 13:17:15 +0000
> @@ -320,7 +320,7 @@ Sensitive_cursor::post_open(THD *thd)
>    lock=           thd->lock;
>    query_id=       thd->query_id;
>    free_list=      thd->free_list;
> -  change_list=    thd->change_list;
> +  thd->change_list.move_elements(&change_list);
>    reset_thd(thd);
>    /* Now we have an active cursor and can cause a deadlock */
>    thd->lock_info.n_cursors++;
> @@ -436,7 +436,7 @@ Sensitive_cursor::fetch(ulong num_rows)
>    thd->open_tables= open_tables;
>    thd->lock= lock;
>    thd->query_id= query_id;
> -  thd->change_list= change_list;
> +  change_list.move_elements(&thd->change_list);
>    /* save references to memory allocated during fetch */
>    thd->set_n_backup_active_arena(this, &backup_arena);
>  
> @@ -458,7 +458,7 @@ Sensitive_cursor::fetch(ulong num_rows)
>    /* Grab free_list here to correctly free it in close */
>    thd->restore_active_arena(this, &backup_arena);
>  
> -  change_list= thd->change_list;
> +  thd->change_list.move_elements(&change_list);
>    reset_thd(thd);
>  
>    for (info= ht_info; info->read_view; info++)
> @@ -505,7 +505,7 @@ Sensitive_cursor::close()
>      info->ht= 0;
>    }
>  
> -  thd->change_list= change_list;
> +  change_list.move_elements(&thd->change_list);
>    {
>      /*
>        XXX: Another hack: we need to set THD state as if in a fetch to be
> @@ -531,7 +531,6 @@ Sensitive_cursor::close()
>    join= 0;
>    stmt_arena= 0;
>    free_items();
> -  change_list.empty();
>    DBUG_VOID_RETURN;
>  }

OK. 

> === modified file 'sql/sql_list.h'
> --- a/sql/sql_list.h	2009-03-28 00:27:25 +0000
> +++ b/sql/sql_list.h	2009-06-16 13:17:15 +0000
> @@ -511,8 +511,9 @@ template <class T> class I_List_iterator
>  
>  class base_ilist
>  {
> +  struct ilink *first;
> +  struct ilink last;
>  public:
> -  struct ilink *first,last;
>    inline void empty() { first= &last; last.prev= &first; }
>    base_ilist() { empty(); }
>    inline bool is_empty() {  return first == &last; }
> @@ -540,7 +541,20 @@ public:
>    {
>      return (first != &last) ? first : 0;
>    }
> -  friend class base_list_iterator;
> +
> +  /* Moves list elements to new owner. */

Please use doxygen changeset comments.

Why do you assert that new_owner is empty? It should be documented
in the method comment.

If your use cases are always such that new_owner is empty, perhaps
you should implement ::swap() instead, that would exchange two
lists? The advantage of swap(), in my view, is that it's a more
commonly used pattern. swap() can be used in all your use cases,
plus in a variety of others.

> +  void move_elements(base_ilist* new_owner) {

Opening bracket should belong to an own line.

> +    DBUG_ASSERT(new_owner->is_empty());
> +    new_owner->first= first;
> +    new_owner->last= last;
> +    empty();
> +  }
> +
> +  friend class base_ilist_iterator;
> + private:
> +  /* Declare, but don't define copy CTOR and assignment operator. */
> +  base_ilist(const base_ilist&);
> +  void operator=(const base_ilist& rhs);

& goes with rhs: const base_ilist &rhs, or just drop the parameter
name altogether.

>  };
>  
>  
> @@ -573,6 +587,9 @@ public:
>    inline void push_back(T* a)	{ base_ilist::push_back(a); }
>    inline T* get()		{ return (T*) base_ilist::get(); }
>    inline T* head()		{ return (T*) base_ilist::head(); }
> +  inline void move_elements(I_List<T>* new_owner) {

  * goes with new_owner, I_List<T> *new_owner

> +    base_ilist::move_elements(new_owner);
> +  }
>  #ifndef _lint
>    friend class I_List_iterator<T>;
>  #endif
> 
> === modified file 'sql/sql_prepare.cc'
> --- a/sql/sql_prepare.cc	2009-06-06 00:02:04 +0000
> +++ b/sql/sql_prepare.cc	2009-06-16 13:17:15 +0000
> @@ -3429,7 +3429,8 @@ Prepared_statement::execute_server_runna
>    Statement stmt_backup;
>    bool error;
>    Query_arena *save_stmt_arena= thd->stmt_arena;
> -  Item_change_list save_change_list= thd->change_list;
> +  Item_change_list save_change_list;
> +  thd->change_list.move_elements(&save_change_list);
>  
>    state= CONVENTIONAL_EXECUTION;
>  
> @@ -3439,7 +3440,6 @@ Prepared_statement::execute_server_runna
>    thd->set_n_backup_statement(this, &stmt_backup);
>    thd->set_n_backup_active_arena(this, &stmt_backup);
>    thd->stmt_arena= this;
> -  thd->change_list.empty();
>  
>    error= server_runnable->execute_server_code(thd);
>  
> @@ -3454,9 +3454,7 @@ Prepared_statement::execute_server_runna
>    thd->restore_backup_statement(this, &stmt_backup);
>    thd->stmt_arena= save_stmt_arena;
>  
> -  DBUG_ASSERT(thd->change_list.is_empty());
> -  thd->change_list= save_change_list;
> -  save_change_list.empty();
> +  save_change_list.move_elements(&thd->change_list);

OK. If you use swap(), please restore that assert back.

>  
>    /* Items and memory will freed in destructor */

Have you run the regression tests?

-- 
Thread
bzr commit into mysql-azalea branch (tor.didriksen:3357) Tor Didriksen17 Jun 2009
  • Re: bzr commit into mysql-azalea branch (tor.didriksen:3357)Konstantin Osipov17 Jun 2009
    • Re: bzr commit into mysql-azalea branch (tor.didriksen:3357)Tor Didriksen18 Jun 2009